mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-12-05 16:51:07 -07:00
Merge remote-tracking branch 'remote/master' into feature/merge_upstream
# Conflicts: # bbl/i18n/OrcaSlicer.pot # bbl/i18n/de/OrcaSlicer_de.po # bbl/i18n/en/OrcaSlicer_en.po # bbl/i18n/es/OrcaSlicer_es.po # bbl/i18n/fr/OrcaSlicer_fr.po # bbl/i18n/hu/OrcaSlicer_hu.po # bbl/i18n/it/OrcaSlicer_it.po # bbl/i18n/ja/OrcaSlicer_ja.po # bbl/i18n/nl/OrcaSlicer_nl.po # bbl/i18n/sv/OrcaSlicer_sv.po # bbl/i18n/zh_cn/OrcaSlicer_zh_CN.po # resources/config.json # resources/i18n/de/BambuStudio.mo # resources/i18n/en/BambuStudio.mo # resources/i18n/es/BambuStudio.mo # resources/i18n/fr/BambuStudio.mo # resources/i18n/hu/BambuStudio.mo # resources/i18n/it/BambuStudio.mo # resources/i18n/ja/OrcaSlicer.mo # resources/i18n/nl/BambuStudio.mo # resources/i18n/sv/BambuStudio.mo # resources/i18n/zh_cn/BambuStudio.mo # resources/images/ams_humidity_2.svg # resources/images/ams_humidity_3.svg # resources/images/ams_humidity_4.svg # resources/images/ams_humidity_tips.svg # resources/images/monitor_state_on.svg # resources/images/sdcard_state_normal.svg # resources/profiles/BBL.json # resources/profiles/BBL/filament/Bambu PETG-CF @base.json # resources/profiles/BBL/filament/Generic PETG-CF @base.json # resources/profiles/BBL/machine/Bambu Lab P1P 0.4 nozzle.json # resources/web/data/text.js # resources/web/guide/3/index.html # resources/web/guide/31/index.html # src/BambuStudio.cpp # src/libslic3r/AABBTreeLines.hpp # src/libslic3r/Brim.cpp # src/libslic3r/CMakeLists.txt # src/libslic3r/ExPolygon.hpp # src/libslic3r/Fill/FillBase.hpp # src/libslic3r/Format/bbs_3mf.cpp # src/libslic3r/GCodeWriter.cpp # src/libslic3r/Line.hpp # src/libslic3r/PerimeterGenerator.cpp # src/libslic3r/Preset.cpp # src/libslic3r/Print.cpp # src/libslic3r/Print.hpp # src/libslic3r/PrintConfig.cpp # src/libslic3r/PrintConfig.hpp # src/libslic3r/TreeSupport.cpp # src/slic3r/GUI/AmsMappingPopup.cpp # src/slic3r/GUI/BackgroundSlicingProcess.cpp # src/slic3r/GUI/ConfigManipulation.cpp # src/slic3r/GUI/GCodeViewer.cpp # src/slic3r/GUI/GCodeViewer.hpp # src/slic3r/GUI/GLCanvas3D.cpp # src/slic3r/GUI/GUI_App.cpp # src/slic3r/GUI/MainFrame.cpp # src/slic3r/GUI/PartPlate.cpp # src/slic3r/GUI/Plater.cpp # src/slic3r/GUI/Preferences.cpp # src/slic3r/GUI/SelectMachine.cpp # src/slic3r/GUI/Widgets/AMSControl.cpp # src/slic3r/GUI/wxMediaCtrl2.cpp # src/slic3r/Utils/Process.cpp # version.inc
This commit is contained in:
commit
9f598046d1
658 changed files with 70312 additions and 4877 deletions
|
|
@ -82,6 +82,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/AuxiliaryDialog.hpp
|
||||
GUI/Auxiliary.cpp
|
||||
GUI/Auxiliary.hpp
|
||||
GUI/Project.cpp
|
||||
GUI/Project.hpp
|
||||
GUI/BackgroundSlicingProcess.cpp
|
||||
GUI/BackgroundSlicingProcess.hpp
|
||||
GUI/BitmapCache.cpp
|
||||
|
|
@ -195,6 +197,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/GUI_Factories.hpp
|
||||
GUI/GUI_ObjectList.cpp
|
||||
GUI/GUI_ObjectList.hpp
|
||||
GUI/GUI_ObjectLayers.cpp
|
||||
GUI/GUI_ObjectLayers.hpp
|
||||
GUI/GUI_AuxiliaryList.cpp
|
||||
GUI/GUI_AuxiliaryList.hpp
|
||||
GUI/GUI_ObjectSettings.cpp
|
||||
|
|
@ -267,6 +271,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/3DBed.hpp
|
||||
GUI/Camera.cpp
|
||||
GUI/Camera.hpp
|
||||
GUI/CameraUtils.cpp
|
||||
GUI/CameraUtils.hpp
|
||||
GUI/wxExtensions.cpp
|
||||
GUI/wxExtensions.hpp
|
||||
GUI/WipeTowerDialog.cpp
|
||||
|
|
|
|||
|
|
@ -569,26 +569,6 @@ Transform3d GLVolume::world_matrix() const
|
|||
return m;
|
||||
}
|
||||
|
||||
//BBS: scaled_matrix
|
||||
Transform3d GLVolume::world_matrix( float scale_factor) const
|
||||
{
|
||||
//const Vec3d& volume_translation = m_volume_transformation.get_offset();
|
||||
//Vec3d scaling_factor = { scale_factor, scale_factor, scale_factor };
|
||||
Vec3d ofs2ass = m_offset_to_assembly * (GLVolume::explosion_ratio - 1.0);
|
||||
Vec3d volofs2obj = m_volume_transformation.get_offset() * (GLVolume::explosion_ratio - 1.0);
|
||||
|
||||
Transform3d volume_matrix = Geometry::assemble_transform(
|
||||
m_volume_transformation.get_offset() + ofs2ass + volofs2obj,
|
||||
m_volume_transformation.get_rotation(),
|
||||
m_volume_transformation.get_scaling_factor() * scale_factor,
|
||||
m_volume_transformation.get_mirror()
|
||||
);
|
||||
Transform3d m = m_instance_transformation.get_matrix() * volume_matrix;
|
||||
|
||||
//m.translation()(2) += m_sla_shift_z;
|
||||
return m;
|
||||
}
|
||||
|
||||
bool GLVolume::is_left_handed() const
|
||||
{
|
||||
const Vec3d &m1 = m_instance_transformation.get_mirror();
|
||||
|
|
@ -834,8 +814,6 @@ void GLVolume::render(bool with_outline) const
|
|||
fclose(file);
|
||||
}
|
||||
#endif
|
||||
|
||||
Transform3d matrix = world_matrix();
|
||||
render_body();
|
||||
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, outline render body, shader name %2%")%__LINE__ %shader->get_name();
|
||||
|
||||
|
|
@ -887,7 +865,8 @@ void GLVolume::render(bool with_outline) const
|
|||
glsafe(::glPopMatrix());
|
||||
glsafe(::glPushMatrix());
|
||||
|
||||
matrix = world_matrix(scale);
|
||||
Transform3d matrix = world_matrix();
|
||||
matrix.scale(scale);
|
||||
glsafe(::glMultMatrixd(matrix.data()));
|
||||
this->indexed_vertex_array.render(this->tverts_range, this->qverts_range);
|
||||
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, outline render for body, shader name %2%")%__LINE__ %shader->get_name();
|
||||
|
|
@ -1065,7 +1044,8 @@ int GLVolumeCollection::load_object_volume(
|
|||
int instance_idx,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized,
|
||||
bool in_assemble_view)
|
||||
bool in_assemble_view,
|
||||
bool use_loaded_id)
|
||||
{
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
const int extruder_id = model_volume->extruder_id();
|
||||
|
|
@ -1100,6 +1080,11 @@ int GLVolumeCollection::load_object_volume(
|
|||
else
|
||||
v.set_instance_transformation(instance->get_transformation());
|
||||
v.set_volume_transformation(model_volume->get_transformation());
|
||||
//use object's instance id
|
||||
if (use_loaded_id && (instance->loaded_id > 0))
|
||||
v.model_object_ID = instance->loaded_id;
|
||||
else
|
||||
v.model_object_ID = instance->id().id;
|
||||
|
||||
return int(this->volumes.size() - 1);
|
||||
}
|
||||
|
|
@ -1287,14 +1272,13 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
|||
#endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
|
||||
|
||||
// render sinking contours of non-hovered volumes
|
||||
//BBS: remove sinking logic
|
||||
/*if (m_show_sinking_contours)
|
||||
if (m_show_sinking_contours)
|
||||
if (volume.first->is_sinking() && !volume.first->is_below_printbed() &&
|
||||
volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) {
|
||||
shader->stop_using();
|
||||
volume.first->render_sinking_contours();
|
||||
shader->start_using();
|
||||
}*/
|
||||
}
|
||||
|
||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
|
||||
|
|
@ -1350,8 +1334,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
|||
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
|
||||
}
|
||||
|
||||
//BBS: remove sinking logic
|
||||
/*if (m_show_sinking_contours) {
|
||||
if (m_show_sinking_contours) {
|
||||
for (GLVolumeWithIdAndZ& volume : to_render) {
|
||||
// render sinking contours of hovered/displaced volumes
|
||||
if (volume.first->is_sinking() && !volume.first->is_below_printbed() &&
|
||||
|
|
@ -1363,7 +1346,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
|||
shader->start_using();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if (disable_cullface)
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
|
|
|
|||
|
|
@ -357,6 +357,8 @@ public:
|
|||
// An ID containing the extruder ID (used to select color).
|
||||
int extruder_id;
|
||||
|
||||
size_t model_object_ID{0};
|
||||
|
||||
// Various boolean flags.
|
||||
struct {
|
||||
// Is this object selected?
|
||||
|
|
@ -501,9 +503,6 @@ public:
|
|||
Transform3d world_matrix() const;
|
||||
bool is_left_handed() const;
|
||||
|
||||
//BBS: world_matrix with scale factor
|
||||
Transform3d world_matrix(float scale_factor) const;
|
||||
|
||||
const BoundingBoxf3& transformed_bounding_box() const;
|
||||
// non-caching variant
|
||||
BoundingBoxf3 transformed_convex_hull_bounding_box(const Transform3d &trafo) const;
|
||||
|
|
@ -637,7 +636,8 @@ public:
|
|||
int instance_idx,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized,
|
||||
bool in_assemble_view = false);
|
||||
bool in_assemble_view = false,
|
||||
bool use_loaded_id = false);
|
||||
|
||||
// Load SLA auxiliary GLVolumes (for support trees or pad).
|
||||
void load_object_auxiliary(
|
||||
|
|
|
|||
|
|
@ -4,12 +4,15 @@
|
|||
#include "GUI_App.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
static bool show_flag;
|
||||
|
||||
wxDEFINE_EVENT(EVT_SELECTED_COLOR, wxCommandEvent);
|
||||
|
||||
AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id)
|
||||
: DPIDialog(parent, id, _L("AMS Materials Setting"), wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
|
||||
, m_color_picker_popup(ColorPickerPopup(this))
|
||||
{
|
||||
create();
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
|
|
@ -39,10 +42,18 @@ void AMSMaterialsSetting::create()
|
|||
m_button_confirm->SetCornerRadius(FromDIP(12));
|
||||
m_button_confirm->Bind(wxEVT_BUTTON, &AMSMaterialsSetting::on_select_ok, this);
|
||||
|
||||
m_button_close = new Button(this, _L("Close"));
|
||||
m_btn_bg_gray = StateColor(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(*wxWHITE, StateColor::Focused),
|
||||
m_button_reset = new Button(this, _L("Reset"));
|
||||
m_btn_bg_gray = StateColor(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(*wxWHITE, StateColor::Focused),
|
||||
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
|
||||
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
|
||||
m_button_reset->SetBackgroundColor(m_btn_bg_gray);
|
||||
m_button_reset->SetBorderColor(AMS_MATERIALS_SETTING_GREY900);
|
||||
m_button_reset->SetTextColor(AMS_MATERIALS_SETTING_GREY900);
|
||||
m_button_reset->SetMinSize(AMS_MATERIALS_SETTING_BUTTON_SIZE);
|
||||
m_button_reset->SetCornerRadius(FromDIP(12));
|
||||
m_button_reset->Bind(wxEVT_BUTTON, &AMSMaterialsSetting::on_select_reset, this);
|
||||
|
||||
m_button_close = new Button(this, _L("Close"));
|
||||
m_button_close->SetBackgroundColor(m_btn_bg_gray);
|
||||
m_button_close->SetBorderColor(AMS_MATERIALS_SETTING_GREY900);
|
||||
m_button_close->SetTextColor(AMS_MATERIALS_SETTING_GREY900);
|
||||
|
|
@ -51,6 +62,7 @@ void AMSMaterialsSetting::create()
|
|||
m_button_close->Bind(wxEVT_BUTTON, &AMSMaterialsSetting::on_select_close, this);
|
||||
|
||||
m_sizer_button->Add(m_button_confirm, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(20));
|
||||
m_sizer_button->Add(m_button_reset, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(20));
|
||||
m_sizer_button->Add(m_button_close, 0, wxALIGN_CENTER, 0);
|
||||
|
||||
m_sizer_main->Add(m_panel_normal, 0, wxALL, FromDIP(2));
|
||||
|
|
@ -96,6 +108,7 @@ void AMSMaterialsSetting::create()
|
|||
});
|
||||
|
||||
Bind(wxEVT_PAINT, &AMSMaterialsSetting::paintEvent, this);
|
||||
Bind(EVT_SELECTED_COLOR, &AMSMaterialsSetting::on_picker_color, this);
|
||||
m_comboBox_filament->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(AMSMaterialsSetting::on_select_filament), NULL, this);
|
||||
}
|
||||
|
||||
|
|
@ -141,17 +154,12 @@ void AMSMaterialsSetting::create_panel_normal(wxWindow* parent)
|
|||
|
||||
m_sizer_colour->Add(0, 0, 0, wxEXPAND, 0);
|
||||
|
||||
m_clrData = new wxColourData();
|
||||
m_clrData->SetChooseFull(true);
|
||||
m_clrData->SetChooseAlpha(false);
|
||||
m_clr_picker = new ColorPicker(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_clr_picker->set_show_full(true);
|
||||
m_clr_picker->SetBackgroundColour(*wxWHITE);
|
||||
|
||||
m_clr_picker = new Button(parent, wxEmptyString, wxEmptyString, wxBU_AUTODRAW);
|
||||
m_clr_picker->SetCanFocus(false);
|
||||
m_clr_picker->SetSize(FromDIP(50), FromDIP(25));
|
||||
m_clr_picker->SetMinSize(wxSize(FromDIP(50), FromDIP(25)));
|
||||
m_clr_picker->SetCornerRadius(FromDIP(6));
|
||||
m_clr_picker->SetBorderColor(wxColour(172, 172, 172));
|
||||
m_clr_picker->Bind(wxEVT_BUTTON, &AMSMaterialsSetting::on_clr_picker, this);
|
||||
|
||||
m_clr_picker->Bind(wxEVT_LEFT_DOWN, &AMSMaterialsSetting::on_clr_picker, this);
|
||||
m_sizer_colour->Add(m_clr_picker, 0, 0, 0);
|
||||
|
||||
wxBoxSizer* m_sizer_temperature = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
|
@ -260,8 +268,9 @@ void AMSMaterialsSetting::create_panel_kn(wxWindow* parent)
|
|||
{
|
||||
auto sizer = new wxBoxSizer(wxVERTICAL);
|
||||
// title
|
||||
auto ratio_text = new wxStaticText(parent, wxID_ANY, _L("Factors of dynamic flow cali"));
|
||||
ratio_text->SetFont(Label::Head_14);
|
||||
m_ratio_text = new wxStaticText(parent, wxID_ANY, _L("Factors of dynamic flow cali"));
|
||||
m_ratio_text->SetForegroundColour(wxColour(50, 58, 61));
|
||||
m_ratio_text->SetFont(Label::Head_14);
|
||||
|
||||
auto kn_val_sizer = new wxFlexGridSizer(0, 2, 0, 0);
|
||||
kn_val_sizer->SetFlexibleDirection(wxBOTH);
|
||||
|
|
@ -295,7 +304,7 @@ void AMSMaterialsSetting::create_panel_kn(wxWindow* parent)
|
|||
m_input_n_val->Hide();
|
||||
|
||||
sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
sizer->Add(ratio_text, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20));
|
||||
sizer->Add(m_ratio_text, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20));
|
||||
sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
sizer->Add(kn_val_sizer, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20));
|
||||
sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
|
|
@ -379,6 +388,62 @@ void AMSMaterialsSetting::enable_confirm_button(bool en)
|
|||
}
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::on_select_reset(wxCommandEvent& event) {
|
||||
MessageDialog msg_dlg(nullptr, _L("Are you sure you want to clear the filament information?"), wxEmptyString, wxICON_WARNING | wxOK | wxCANCEL);
|
||||
auto result = msg_dlg.ShowModal();
|
||||
if (result != wxID_OK)
|
||||
return;
|
||||
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue("");
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue("");
|
||||
ams_filament_id = "";
|
||||
ams_setting_id = "";
|
||||
wxString k_text = "0.000";
|
||||
wxString n_text = "0.000";
|
||||
m_filament_type = "";
|
||||
long nozzle_temp_min_int = 0;
|
||||
long nozzle_temp_max_int = 0;
|
||||
wxColour color = *wxWHITE;
|
||||
char col_buf[10];
|
||||
sprintf(col_buf, "%02X%02X%02XFF", (int)color.Red(), (int)color.Green(), (int)color.Blue());
|
||||
|
||||
if (obj) {
|
||||
// set filament
|
||||
if (obj->is_support_filament_edit_virtual_tray || !is_virtual_tray()) {
|
||||
if (is_virtual_tray()) {
|
||||
obj->command_ams_filament_settings(255, VIRTUAL_TRAY_ID, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int);
|
||||
}
|
||||
else {
|
||||
obj->command_ams_filament_settings(ams_id, tray_id, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int);
|
||||
}
|
||||
}
|
||||
|
||||
// set k / n value
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY)) {
|
||||
// set extrusion cali ratio
|
||||
int cali_tray_id = ams_id * 4 + tray_id;
|
||||
|
||||
double k = 0.0;
|
||||
try {
|
||||
k_text.ToDouble(&k);
|
||||
}
|
||||
catch (...) {
|
||||
;
|
||||
}
|
||||
|
||||
double n = 0.0;
|
||||
try {
|
||||
n_text.ToDouble(&n);
|
||||
}
|
||||
catch (...) {
|
||||
;
|
||||
}
|
||||
obj->command_extrusion_cali_set(cali_tray_id, "", "", k, n);
|
||||
}
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
||||
{
|
||||
wxString k_text = m_input_k_val->GetTextCtrl()->GetValue();
|
||||
|
|
@ -408,10 +473,11 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
}
|
||||
obj->command_extrusion_cali_set(VIRTUAL_TRAY_ID, "", "", k, n);
|
||||
Close();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!m_is_third) {
|
||||
// check and set k n
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY)) {
|
||||
if (!ExtrusionCalibration::check_k_validation(k_text)) {
|
||||
wxString k_tips = _L("Please input a valid value (K in 0~0.5)");
|
||||
wxString kn_tips = _L("Please input a valid value (K in 0~0.5, N in 0.6~2.0)");
|
||||
|
|
@ -423,7 +489,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
|
||||
|
||||
// set k / n value
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY)) {
|
||||
// set extrusion cali ratio
|
||||
int cali_tray_id = ams_id * 4 + tray_id;
|
||||
|
||||
|
|
@ -448,34 +514,68 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
return;
|
||||
}
|
||||
wxString nozzle_temp_min = m_input_nozzle_min->GetTextCtrl()->GetValue();
|
||||
auto filament = m_comboBox_filament->GetValue();
|
||||
auto filament = m_comboBox_filament->GetValue();
|
||||
|
||||
wxString nozzle_temp_max = m_input_nozzle_max->GetTextCtrl()->GetValue();
|
||||
|
||||
long nozzle_temp_min_int, nozzle_temp_max_int;
|
||||
nozzle_temp_min.ToLong(&nozzle_temp_min_int);
|
||||
nozzle_temp_max.ToLong(&nozzle_temp_max_int);
|
||||
wxColour color = m_clrData->GetColour();
|
||||
wxColour color = m_clr_picker->m_colour;
|
||||
char col_buf[10];
|
||||
sprintf(col_buf, "%02X%02X%02XFF", (int) color.Red(), (int) color.Green(), (int) color.Blue());
|
||||
sprintf(col_buf, "%02X%02X%02XFF", (int)color.Red(), (int)color.Green(), (int)color.Blue());
|
||||
ams_filament_id = "";
|
||||
ams_setting_id = "";
|
||||
|
||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
if (preset_bundle) {
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
|
||||
|
||||
if (it->alias.compare(m_comboBox_filament->GetValue().ToStdString()) == 0) {
|
||||
|
||||
|
||||
//check is it in the filament blacklist
|
||||
if(!is_virtual_tray()){
|
||||
bool in_blacklist = false;
|
||||
std::string action;
|
||||
std::string info;
|
||||
std::string filamnt_type;
|
||||
it->get_filament_type(filamnt_type);
|
||||
|
||||
if (it->vendor) {
|
||||
DeviceManager::check_filaments_in_blacklist(it->vendor->name, filamnt_type, in_blacklist, action, info);
|
||||
}
|
||||
|
||||
if (in_blacklist) {
|
||||
if (action == "prohibition") {
|
||||
MessageDialog msg_wingow(nullptr, info, _L("Error"), wxICON_WARNING | wxOK);
|
||||
msg_wingow.ShowModal();
|
||||
//m_comboBox_filament->SetSelection(m_filament_selection);
|
||||
return;
|
||||
}
|
||||
else if (action == "warning") {
|
||||
MessageDialog msg_wingow(nullptr, info, _L("Warning"), wxICON_INFORMATION | wxOK);
|
||||
msg_wingow.ShowModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ams_filament_id = it->filament_id;
|
||||
ams_setting_id = it->setting_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ams_filament_id.empty() || nozzle_temp_min.empty() || nozzle_temp_max.empty() || m_filament_type.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Invalid Setting id";
|
||||
} else {
|
||||
MessageDialog msg_dlg(nullptr, _L("You need to select the material type and color first."), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (obj) {
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY)) {
|
||||
if (!ExtrusionCalibration::check_k_validation(k_text)) {
|
||||
wxString k_tips = _L("Please input a valid value (K in 0~0.5)");
|
||||
wxString kn_tips = _L("Please input a valid value (K in 0~0.5, N in 0.6~2.0)");
|
||||
|
|
@ -489,13 +589,14 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
if (obj->is_support_filament_edit_virtual_tray || !is_virtual_tray()) {
|
||||
if (is_virtual_tray()) {
|
||||
obj->command_ams_filament_settings(255, VIRTUAL_TRAY_ID, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
obj->command_ams_filament_settings(ams_id, tray_id, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int);
|
||||
}
|
||||
}
|
||||
|
||||
// set k / n value
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY)) {
|
||||
// set extrusion cali ratio
|
||||
int cali_tray_id = ams_id * 4 + tray_id;
|
||||
|
||||
|
|
@ -529,15 +630,47 @@ void AMSMaterialsSetting::on_select_close(wxCommandEvent &event)
|
|||
|
||||
void AMSMaterialsSetting::set_color(wxColour color)
|
||||
{
|
||||
m_clrData->SetColour(color);
|
||||
//m_clrData->SetColour(color);
|
||||
m_clr_picker->set_color(color);
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::on_clr_picker(wxCommandEvent & event)
|
||||
void AMSMaterialsSetting::set_colors(std::vector<wxColour> colors)
|
||||
{
|
||||
//m_clrData->SetColour(color);
|
||||
m_clr_picker->set_colors(colors);
|
||||
}
|
||||
|
||||
|
||||
void AMSMaterialsSetting::on_picker_color(wxCommandEvent& event)
|
||||
{
|
||||
unsigned int color_num = event.GetInt();
|
||||
set_color(wxColour(color_num>>16&0xFF, color_num>>8&0xFF, color_num&0xFF));
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::on_clr_picker(wxMouseEvent &event)
|
||||
{
|
||||
if(!m_is_third || obj->is_in_printing() || obj->can_resume())
|
||||
return;
|
||||
auto clr_dialog = new wxColourDialog(this, m_clrData);
|
||||
show_flag = true;
|
||||
|
||||
|
||||
std::vector<wxColour> ams_colors;
|
||||
for (auto ams_it = obj->amsList.begin(); ams_it != obj->amsList.end(); ++ams_it) {
|
||||
for (auto tray_id = ams_it->second->trayList.begin(); tray_id != ams_it->second->trayList.end(); ++tray_id) {
|
||||
std::vector<wxColour>::iterator iter = find(ams_colors.begin(), ams_colors.end(), AmsTray::decode_color(tray_id->second->color));
|
||||
if (iter == ams_colors.end()) {
|
||||
ams_colors.push_back(AmsTray::decode_color(tray_id->second->color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxPoint img_pos = m_clr_picker->ClientToScreen(wxPoint(0, 0));
|
||||
wxPoint popup_pos(img_pos.x + FromDIP(50), img_pos.y);
|
||||
m_color_picker_popup.Position(popup_pos, wxSize(0, 0));
|
||||
m_color_picker_popup.set_ams_colours(ams_colors);
|
||||
m_color_picker_popup.set_def_colour(m_clr_picker->m_colour);
|
||||
m_color_picker_popup.Popup();
|
||||
|
||||
/*auto clr_dialog = new wxColourDialog(this, m_clrData);
|
||||
if (clr_dialog->ShowModal() == wxID_OK) {
|
||||
m_clrData = &(clr_dialog->GetColourData());
|
||||
m_clr_picker->SetBackgroundColor(wxColour(
|
||||
|
|
@ -546,7 +679,7 @@ void AMSMaterialsSetting::on_clr_picker(wxCommandEvent & event)
|
|||
m_clrData->GetColour().Blue(),
|
||||
254
|
||||
));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
bool AMSMaterialsSetting::is_virtual_tray()
|
||||
|
|
@ -565,7 +698,7 @@ void AMSMaterialsSetting::update_widgets()
|
|||
else
|
||||
m_panel_normal->Hide();
|
||||
m_panel_kn->Show();
|
||||
} else if (obj && obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
|
||||
} else if (obj && obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY)) {
|
||||
m_panel_normal->Show();
|
||||
m_panel_kn->Show();
|
||||
} else {
|
||||
|
|
@ -581,7 +714,21 @@ bool AMSMaterialsSetting::Show(bool show)
|
|||
m_button_confirm->SetMinSize(AMS_MATERIALS_SETTING_BUTTON_SIZE);
|
||||
m_input_nozzle_max->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
|
||||
m_clr_picker->SetBackgroundColour(m_clr_picker->GetParent()->GetBackgroundColour());
|
||||
//m_clr_picker->set_color(m_clr_picker->GetParent()->GetBackgroundColour());
|
||||
|
||||
if (obj && obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
|
||||
m_ratio_text->Show();
|
||||
m_k_param->Show();
|
||||
m_input_k_val->Show();
|
||||
}
|
||||
else {
|
||||
m_ratio_text->Hide();
|
||||
m_k_param->Hide();
|
||||
m_input_k_val->Hide();
|
||||
}
|
||||
Layout();
|
||||
Fit();
|
||||
wxGetApp().UpdateDarkUI(this);
|
||||
}
|
||||
return DPIDialog::Show(show);
|
||||
}
|
||||
|
|
@ -599,6 +746,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
|||
m_input_n_val->GetTextCtrl()->SetValue(n);
|
||||
|
||||
if (is_virtual_tray() && obj && !obj->is_support_filament_edit_virtual_tray) {
|
||||
m_button_reset->Show();
|
||||
m_button_confirm->Show();
|
||||
update();
|
||||
Layout();
|
||||
|
|
@ -606,15 +754,16 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
|||
ShowModal();
|
||||
return;
|
||||
} else {
|
||||
m_clr_picker->SetBackgroundColor(wxColour(
|
||||
/* m_clr_picker->set_color(wxColour(
|
||||
m_clrData->GetColour().Red(),
|
||||
m_clrData->GetColour().Green(),
|
||||
m_clrData->GetColour().Blue(),
|
||||
254
|
||||
));
|
||||
));*/
|
||||
|
||||
if (!m_is_third) {
|
||||
if (obj && obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
|
||||
m_button_reset->Hide();
|
||||
if (obj && obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY)) {
|
||||
m_button_confirm->Show();
|
||||
} else {
|
||||
m_button_confirm->Hide();
|
||||
|
|
@ -636,6 +785,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
|||
return;
|
||||
}
|
||||
|
||||
m_button_reset->Show();
|
||||
m_button_confirm->Show();
|
||||
m_panel_SN->Hide();
|
||||
m_comboBox_filament->Show();
|
||||
|
|
@ -721,37 +871,18 @@ void AMSMaterialsSetting::post_select_event() {
|
|||
wxPostEvent(m_comboBox_filament, event);
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::msw_rescale()
|
||||
{
|
||||
m_clr_picker->msw_rescale();
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
{
|
||||
m_filament_type = "";
|
||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
if (preset_bundle) {
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
|
||||
if (it->alias.compare(m_comboBox_filament->GetValue().ToStdString()) == 0) {
|
||||
|
||||
//check is it in the filament blacklist
|
||||
bool in_blacklist = false;
|
||||
std::string action;
|
||||
std::string info;
|
||||
std::string filamnt_type;
|
||||
it->get_filament_type(filamnt_type);
|
||||
|
||||
if (it->vendor) {
|
||||
DeviceManager::check_filaments_in_blacklist(it->vendor->name, filamnt_type, in_blacklist, action, info);
|
||||
}
|
||||
|
||||
if (in_blacklist) {
|
||||
if (action == "prohibition") {
|
||||
MessageDialog msg_wingow(nullptr, info, _L("Error"), wxICON_WARNING | wxOK);
|
||||
msg_wingow.ShowModal();
|
||||
m_comboBox_filament->SetSelection(m_filament_selection);
|
||||
return;
|
||||
}
|
||||
else if (action == "warning") {
|
||||
MessageDialog msg_wingow(nullptr, info, _L("Warning"), wxICON_INFORMATION | wxOK);
|
||||
msg_wingow.ShowModal();
|
||||
}
|
||||
}
|
||||
if (!m_comboBox_filament->GetValue().IsEmpty() && it->alias.compare(m_comboBox_filament->GetValue().ToStdString()) == 0) {
|
||||
|
||||
// ) if nozzle_temperature_range is found
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
|
|
@ -789,10 +920,10 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
|||
}
|
||||
}
|
||||
if (m_input_nozzle_min->GetTextCtrl()->GetValue().IsEmpty()) {
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue("220");
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue("0");
|
||||
}
|
||||
if (m_input_nozzle_max->GetTextCtrl()->GetValue().IsEmpty()) {
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue("220");
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue("0");
|
||||
}
|
||||
|
||||
m_filament_selection = evt.GetSelection();
|
||||
|
|
@ -800,4 +931,297 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
|||
|
||||
void AMSMaterialsSetting::on_dpi_changed(const wxRect &suggested_rect) { this->Refresh(); }
|
||||
|
||||
ColorPicker::ColorPicker(wxWindow* parent, wxWindowID id, const wxPoint& pos /*= wxDefaultPosition*/, const wxSize& size /*= wxDefaultSize*/)
|
||||
{
|
||||
wxWindow::Create(parent, id, pos, size);
|
||||
|
||||
SetSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||
SetMinSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||
SetMaxSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||
|
||||
Bind(wxEVT_PAINT, &ColorPicker::paintEvent, this);
|
||||
m_bitmap_border = create_scaled_bitmap("color_picker_border", nullptr, 25);
|
||||
}
|
||||
|
||||
ColorPicker::~ColorPicker(){}
|
||||
|
||||
void ColorPicker::msw_rescale()
|
||||
{
|
||||
m_bitmap_border = create_scaled_bitmap("color_picker_border", nullptr, 25);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ColorPicker::set_color(wxColour col)
|
||||
{
|
||||
m_colour = col;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ColorPicker::set_colors(std::vector<wxColour> cols)
|
||||
{
|
||||
m_cols = cols;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ColorPicker::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void ColorPicker::render(wxDC& dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxSize size = GetSize();
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 });
|
||||
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ColorPicker::doRender(wxDC& dc)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
|
||||
auto radius = m_show_full?size.x / 2:size.x / 2 - FromDIP(1);
|
||||
if (m_selected) radius -= FromDIP(1);
|
||||
|
||||
dc.SetPen(wxPen(m_colour));
|
||||
dc.SetBrush(wxBrush(m_colour));
|
||||
dc.DrawCircle(size.x / 2, size.x / 2, radius);
|
||||
|
||||
if (m_selected) {
|
||||
dc.SetPen(wxPen(m_colour));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawCircle(size.x / 2, size.x / 2, size.x / 2);
|
||||
}
|
||||
|
||||
if (m_show_full) {
|
||||
dc.SetPen(wxPen(wxColour(0x6B6B6B)));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawCircle(size.x / 2, size.x / 2, radius);
|
||||
|
||||
if (m_cols.size() > 1) {
|
||||
int left = FromDIP(0);
|
||||
float total_width = size.x;
|
||||
int gwidth = std::round(total_width / (m_cols.size() - 1));
|
||||
|
||||
for (int i = 0; i < m_cols.size() - 1; i++) {
|
||||
|
||||
if ((left + gwidth) > (size.x)) {
|
||||
gwidth = size.x - left;
|
||||
}
|
||||
|
||||
auto rect = wxRect(left, 0, gwidth, size.y);
|
||||
dc.GradientFillLinear(rect, m_cols[i], m_cols[i + 1], wxEAST);
|
||||
left += gwidth;
|
||||
}
|
||||
dc.DrawBitmap(m_bitmap_border, wxPoint(0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColorPickerPopup::ColorPickerPopup(wxWindow* parent)
|
||||
:PopupWindow(parent, wxBORDER_NONE)
|
||||
{
|
||||
m_def_colors.clear();
|
||||
m_def_colors.push_back(wxColour(0xFFFFFF));
|
||||
m_def_colors.push_back(wxColour(0xfff144));
|
||||
m_def_colors.push_back(wxColour(0xDCF478));
|
||||
m_def_colors.push_back(wxColour(0x0ACC38));
|
||||
m_def_colors.push_back(wxColour(0x057748));
|
||||
m_def_colors.push_back(wxColour(0x0d6284));
|
||||
m_def_colors.push_back(wxColour(0x0EE2A0));
|
||||
m_def_colors.push_back(wxColour(0x76D9F4));
|
||||
m_def_colors.push_back(wxColour(0x46a8f9));
|
||||
m_def_colors.push_back(wxColour(0x2850E0));
|
||||
m_def_colors.push_back(wxColour(0x443089));
|
||||
m_def_colors.push_back(wxColour(0xA03CF7));
|
||||
m_def_colors.push_back(wxColour(0xF330F9));
|
||||
m_def_colors.push_back(wxColour(0xD4B1DD));
|
||||
m_def_colors.push_back(wxColour(0xf95d73));
|
||||
m_def_colors.push_back(wxColour(0xf72323));
|
||||
m_def_colors.push_back(wxColour(0x7c4b00));
|
||||
m_def_colors.push_back(wxColour(0xf98c36));
|
||||
m_def_colors.push_back(wxColour(0xfcecd6));
|
||||
m_def_colors.push_back(wxColour(0xD3C5A3));
|
||||
m_def_colors.push_back(wxColour(0xAF7933));
|
||||
m_def_colors.push_back(wxColour(0x898989));
|
||||
m_def_colors.push_back(wxColour(0xBCBCBC));
|
||||
m_def_colors.push_back(wxColour(0x161616));
|
||||
|
||||
|
||||
SetBackgroundColour(wxColour(*wxWHITE));
|
||||
|
||||
wxBoxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer* m_sizer_box = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_def_color_box = new StaticBox(this);
|
||||
wxBoxSizer* m_sizer_ams = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto m_title_ams = new wxStaticText(m_def_color_box, wxID_ANY, _L("AMS"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_title_ams->SetFont(::Label::Body_14);
|
||||
m_title_ams->SetBackgroundColour(wxColour(238, 238, 238));
|
||||
m_sizer_ams->Add(m_title_ams, 0, wxALL, 5);
|
||||
auto ams_line = new wxPanel(m_def_color_box, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
|
||||
ams_line->SetBackgroundColour(wxColour(0xCECECE));
|
||||
ams_line->SetMinSize(wxSize(-1, 1));
|
||||
ams_line->SetMaxSize(wxSize(-1, 1));
|
||||
m_sizer_ams->Add(ams_line, 1, wxALIGN_CENTER, 0);
|
||||
|
||||
|
||||
m_def_color_box->SetCornerRadius(FromDIP(10));
|
||||
m_def_color_box->SetBackgroundColor(StateColor(std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Normal)));
|
||||
m_def_color_box->SetBorderColor(StateColor(std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Normal)));
|
||||
|
||||
//ams
|
||||
m_ams_fg_sizer = new wxFlexGridSizer(0, 8, 0, 0);
|
||||
m_ams_fg_sizer->SetFlexibleDirection(wxBOTH);
|
||||
m_ams_fg_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
|
||||
|
||||
//other
|
||||
wxFlexGridSizer* fg_sizer;
|
||||
fg_sizer = new wxFlexGridSizer(0, 8, 0, 0);
|
||||
fg_sizer->SetFlexibleDirection(wxBOTH);
|
||||
fg_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
|
||||
|
||||
|
||||
for (wxColour col : m_def_colors) {
|
||||
auto cp = new ColorPicker(m_def_color_box, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
cp->set_color(col);
|
||||
cp->set_selected(false);
|
||||
cp->SetBackgroundColour(StateColor::darkModeColorFor(wxColour(238,238,238)));
|
||||
m_color_pickers.push_back(cp);
|
||||
fg_sizer->Add(cp, 0, wxALL, FromDIP(3));
|
||||
cp->Bind(wxEVT_LEFT_DOWN, [this, cp](auto& e) {
|
||||
set_def_colour(cp->m_colour);
|
||||
|
||||
wxCommandEvent evt(EVT_SELECTED_COLOR);
|
||||
unsigned long g_col = ((cp->m_colour.Red() & 0xff) << 16) + ((cp->m_colour.Green() & 0xff) << 8) + (cp->m_colour.Blue() & 0xff);
|
||||
evt.SetInt(g_col);
|
||||
wxPostEvent(GetParent(), evt);
|
||||
});
|
||||
}
|
||||
|
||||
wxBoxSizer* m_sizer_other = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto m_title_other = new wxStaticText(m_def_color_box, wxID_ANY, _L("Other color"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_title_other->SetFont(::Label::Body_14);
|
||||
m_title_other->SetBackgroundColour(wxColour(238, 238, 238));
|
||||
m_sizer_other->Add(m_title_other, 0, wxALL, 5);
|
||||
auto other_line = new wxPanel(m_def_color_box, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
|
||||
other_line->SetMinSize(wxSize(-1, 1));
|
||||
other_line->SetMaxSize(wxSize(-1, 1));
|
||||
other_line->SetBackgroundColour(wxColour(0xCECECE));
|
||||
m_sizer_other->Add(other_line, 1, wxALIGN_CENTER, 0);
|
||||
|
||||
m_sizer_box->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
m_sizer_box->Add(m_sizer_ams, 1, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
|
||||
m_sizer_box->Add(m_ams_fg_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
|
||||
m_sizer_box->Add(m_sizer_other, 1, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
|
||||
m_sizer_box->Add(fg_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
|
||||
m_sizer_box->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
|
||||
|
||||
m_def_color_box->SetSizer(m_sizer_box);
|
||||
m_def_color_box->Layout();
|
||||
m_def_color_box->Fit();
|
||||
|
||||
m_sizer_main->Add(m_def_color_box, 0, wxALL | wxEXPAND, 10);
|
||||
SetSizer(m_sizer_main);
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
Bind(wxEVT_PAINT, &ColorPickerPopup::paintEvent, this);
|
||||
wxGetApp().UpdateDarkUIWin(this);
|
||||
}
|
||||
|
||||
|
||||
void ColorPickerPopup::set_ams_colours(std::vector<wxColour> ams)
|
||||
{
|
||||
if (m_ams_color_pickers.size() > 0) {
|
||||
for (ColorPicker* col_pick:m_ams_color_pickers) {
|
||||
|
||||
std::vector<ColorPicker*>::iterator iter = find(m_color_pickers.begin(), m_color_pickers.end(), col_pick);
|
||||
if (iter != m_color_pickers.end()) {
|
||||
col_pick->Destroy();
|
||||
m_color_pickers.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
m_ams_color_pickers.clear();
|
||||
}
|
||||
|
||||
|
||||
m_ams_colors = ams;
|
||||
for (wxColour col : m_ams_colors) {
|
||||
auto cp = new ColorPicker(m_def_color_box, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
cp->set_color(col);
|
||||
cp->set_selected(false);
|
||||
cp->SetBackgroundColour(StateColor::darkModeColorFor(wxColour(238,238,238)));
|
||||
m_color_pickers.push_back(cp);
|
||||
m_ams_color_pickers.push_back(cp);
|
||||
m_ams_fg_sizer->Add(cp, 0, wxALL, FromDIP(3));
|
||||
cp->Bind(wxEVT_LEFT_DOWN, [this, cp](auto& e) {
|
||||
set_def_colour(cp->m_colour);
|
||||
|
||||
wxCommandEvent evt(EVT_SELECTED_COLOR);
|
||||
unsigned long g_col = ((cp->m_colour.Red() & 0xff) << 16) + ((cp->m_colour.Green() & 0xff) << 8) + (cp->m_colour.Blue() & 0xff);
|
||||
evt.SetInt(g_col);
|
||||
wxPostEvent(GetParent(), evt);
|
||||
});
|
||||
}
|
||||
m_ams_fg_sizer->Layout();
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
|
||||
void ColorPickerPopup::set_def_colour(wxColour col)
|
||||
{
|
||||
m_def_col = col;
|
||||
|
||||
for (ColorPicker* cp : m_color_pickers) {
|
||||
if (cp->m_selected) {
|
||||
cp->set_selected(false);
|
||||
}
|
||||
}
|
||||
|
||||
for (ColorPicker* cp : m_color_pickers) {
|
||||
if (cp->m_colour == m_def_col) {
|
||||
cp->set_selected(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Dismiss();
|
||||
}
|
||||
|
||||
void ColorPickerPopup::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
dc.SetPen(wxColour(0xAC, 0xAC, 0xAC));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0);
|
||||
}
|
||||
|
||||
void ColorPickerPopup::OnDismiss() {}
|
||||
|
||||
void ColorPickerPopup::Popup()
|
||||
{
|
||||
PopupWindow::Popup();
|
||||
}
|
||||
|
||||
bool ColorPickerPopup::ProcessLeftDown(wxMouseEvent& event) {
|
||||
return PopupWindow::ProcessLeftDown(event);
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
|
|
|||
|
|
@ -28,6 +28,54 @@
|
|||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
class ColorPicker : public wxWindow
|
||||
{
|
||||
public:
|
||||
wxBitmap m_bitmap_border;
|
||||
wxColour m_colour;
|
||||
std::vector<wxColour> m_cols;
|
||||
bool m_selected{false};
|
||||
bool m_show_full{false};
|
||||
|
||||
ColorPicker(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
|
||||
~ColorPicker();
|
||||
|
||||
void msw_rescale();
|
||||
void set_color(wxColour col);
|
||||
void set_colors(std::vector<wxColour> cols);
|
||||
void set_selected(bool sel) {m_selected = sel;Refresh();};
|
||||
void set_show_full(bool full) {m_show_full = full;Refresh();};
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void render(wxDC& dc);
|
||||
void doRender(wxDC& dc);
|
||||
};
|
||||
|
||||
class ColorPickerPopup : public PopupWindow
|
||||
{
|
||||
public:
|
||||
StaticBox* m_def_color_box;
|
||||
wxFlexGridSizer* m_ams_fg_sizer;
|
||||
wxColour m_def_col;
|
||||
std::vector<wxColour> m_def_colors;
|
||||
std::vector<wxColour> m_ams_colors;
|
||||
std::vector<ColorPicker*> m_color_pickers;
|
||||
std::vector<ColorPicker*> m_ams_color_pickers;
|
||||
|
||||
public:
|
||||
ColorPickerPopup(wxWindow* parent);
|
||||
~ColorPickerPopup() {};
|
||||
void set_ams_colours(std::vector<wxColour> ams);
|
||||
void set_def_colour(wxColour col);
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void Popup();
|
||||
virtual void OnDismiss() wxOVERRIDE;
|
||||
virtual bool ProcessLeftDown(wxMouseEvent& event) wxOVERRIDE;
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
|
||||
class AMSMaterialsSetting : public DPIDialog
|
||||
{
|
||||
public:
|
||||
|
|
@ -46,10 +94,12 @@ public:
|
|||
wxString k = wxEmptyString, wxString n = wxEmptyString);
|
||||
|
||||
void post_select_event();
|
||||
|
||||
void msw_rescale();
|
||||
void set_color(wxColour color);
|
||||
void set_colors(std::vector<wxColour> colors);
|
||||
|
||||
MachineObject *obj{nullptr};
|
||||
void on_picker_color(wxCommandEvent& color);
|
||||
MachineObject* obj{ nullptr };
|
||||
int ams_id { 0 }; /* 0 ~ 3 */
|
||||
int tray_id { 0 }; /* 0 ~ 3 */
|
||||
|
||||
|
|
@ -62,6 +112,7 @@ public:
|
|||
wxString m_brand_tmp;
|
||||
wxColour m_brand_colour;
|
||||
std::string m_filament_type;
|
||||
ColorPickerPopup m_color_picker_popup;
|
||||
|
||||
protected:
|
||||
void create_panel_normal(wxWindow* parent);
|
||||
|
|
@ -69,8 +120,9 @@ protected:
|
|||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
void on_select_filament(wxCommandEvent& evt);
|
||||
void on_select_ok(wxCommandEvent &event);
|
||||
void on_select_reset(wxCommandEvent &event);
|
||||
void on_select_close(wxCommandEvent &event);
|
||||
void on_clr_picker(wxCommandEvent &event);
|
||||
void on_clr_picker(wxMouseEvent &event);
|
||||
bool is_virtual_tray();
|
||||
void update_widgets();
|
||||
|
||||
|
|
@ -87,13 +139,15 @@ protected:
|
|||
wxStaticText * m_title_temperature;
|
||||
TextInput * m_input_nozzle_min;
|
||||
TextInput* m_input_nozzle_max;
|
||||
Button * m_button_reset;
|
||||
Button * m_button_confirm;
|
||||
wxStaticText* m_tip_readonly;
|
||||
Button * m_button_close;
|
||||
Button * m_clr_picker;
|
||||
ColorPicker * m_clr_picker;
|
||||
wxColourData * m_clrData;
|
||||
|
||||
wxPanel * m_panel_kn;
|
||||
wxStaticText* m_ratio_text;
|
||||
wxStaticText* m_k_param;
|
||||
TextInput* m_input_k_val;
|
||||
wxStaticText* m_n_param;
|
||||
|
|
@ -108,6 +162,8 @@ protected:
|
|||
TextInput* m_readonly_filament;
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(EVT_SELECTED_COLOR, wxCommandEvent);
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ void AMSSetting::create()
|
|||
m_checkbox_switch_filament->Bind(wxEVT_TOGGLEBUTTON, &AMSSetting::on_switch_filament, this);
|
||||
m_sizer_switch_filament->Add(m_checkbox_switch_filament, 0, wxTOP, 1);
|
||||
m_sizer_switch_filament->Add(0, 0, 0, wxLEFT, 12);
|
||||
m_title_switch_filament = new wxStaticText(m_panel_body, wxID_ANY, _L("AMS auto switch filament"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_title_switch_filament = new wxStaticText(m_panel_body, wxID_ANY, _L("AMS filament backup"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_title_switch_filament->SetFont(::Label::Head_13);
|
||||
m_title_switch_filament->SetForegroundColour(AMS_SETTING_GREY800);
|
||||
m_title_switch_filament->Wrap(AMS_SETTING_BODY_WIDTH);
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ AboutDialog::AboutDialog()
|
|||
|
||||
wxBoxSizer *text_sizer_horiz = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer *text_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
text_sizer_horiz->Add( 0, 0, 0, wxLEFT, FromDIP(23));
|
||||
text_sizer_horiz->Add( 0, 0, 0, wxLEFT, FromDIP(20));
|
||||
|
||||
std::vector<wxString> text_list;
|
||||
text_list.push_back(_L("OrcaSlicer is based on BambuStudio, PrusaSlicer, and SuperSlicer."));
|
||||
|
|
@ -318,8 +318,7 @@ AboutDialog::AboutDialog()
|
|||
wxBoxSizer *copyright_ver_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *copyright_hor_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
copyright_hor_sizer->Add(copyright_ver_sizer, 0, wxALL,5);
|
||||
copyright_hor_sizer->Add( 0, 0, 0, wxLEFT, FromDIP(120));
|
||||
copyright_hor_sizer->Add(copyright_ver_sizer, 0, wxLEFT, FromDIP(20));
|
||||
|
||||
wxStaticText *html_text = new wxStaticText(this, wxID_ANY, "Copyright(C) 2022-2023 Li Jiang All Rights Reserved", wxDefaultPosition, wxDefaultSize);
|
||||
html_text->SetForegroundColour(wxColour(107, 107, 107));
|
||||
|
|
@ -364,10 +363,10 @@ AboutDialog::AboutDialog()
|
|||
copyright_button_ver->Add( 0, 0, 0, wxTOP, FromDIP(10));
|
||||
copyright_button_ver->Add(button_portions, 0, wxALL,0);
|
||||
|
||||
copyright_hor_sizer->Add(copyright_button_ver, 0, wxALL,0);
|
||||
copyright_hor_sizer->Add( 0, 0, 0, wxRIGHT, FromDIP(13));
|
||||
copyright_hor_sizer->AddStretchSpacer();
|
||||
copyright_hor_sizer->Add(copyright_button_ver, 0, wxRIGHT, FromDIP(20));
|
||||
|
||||
ver_sizer->Add(copyright_hor_sizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL,0);
|
||||
ver_sizer->Add(copyright_hor_sizer, 0, wxEXPAND ,0);
|
||||
ver_sizer->Add( 0, 0, 0, wxTOP, FromDIP(30));
|
||||
button_portions->Bind(wxEVT_BUTTON, &AboutDialog::onCopyrightBtn, this);
|
||||
|
||||
|
|
|
|||
|
|
@ -273,6 +273,14 @@ void MaterialItem::doRender(wxDC &dc)
|
|||
SetSizer(m_sizer_main);
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
Bind(wxEVT_SHOW, [this](wxShowEvent& e) {
|
||||
if (e.IsShown() && m_parent_item) {
|
||||
wxPoint pos = m_parent_item->ClientToScreen(wxPoint(0, 0));
|
||||
pos.y += m_parent_item->GetRect().height;
|
||||
this->Move(pos);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
wxString AmsMapingPopup::format_text(wxString &m_msg)
|
||||
|
|
@ -772,47 +780,48 @@ AmsHumidityTipPopup::AmsHumidityTipPopup(wxWindow* parent)
|
|||
wxBoxSizer* m_sizer_tips = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_staticText1 = new Label(this, _L("Cabin humidity"));
|
||||
m_staticText1->SetForegroundColour(wxColour(0x352F2D));
|
||||
m_staticText1->SetFont(::Label::Head_13);
|
||||
|
||||
|
||||
m_staticText2 = new Label(this, _L("Green means that AMS humidity is normal, orange represent humidity is high, red represent humidity is too high.(Hygrometer: lower the better.)"));
|
||||
m_staticText2->SetFont(::Label::Body_13);
|
||||
m_staticText2->SetSize(wxSize(FromDIP(360), -1));
|
||||
m_staticText2->SetMinSize(wxSize(FromDIP(360), -1));
|
||||
m_staticText2->SetMaxSize(wxSize(FromDIP(360), -1));
|
||||
m_staticText2->Wrap(FromDIP(360));
|
||||
m_staticText2->SetSize(wxSize(FromDIP(357), -1));
|
||||
m_staticText2->SetMinSize(wxSize(FromDIP(357), -1));
|
||||
m_staticText2->SetMaxSize(wxSize(FromDIP(357), -1));
|
||||
m_staticText2->Wrap(FromDIP(357));
|
||||
|
||||
|
||||
m_staticText3 = new Label(this, _L("Desiccant status"));
|
||||
m_staticText3->SetForegroundColour(wxColour(0x352F2D));
|
||||
m_staticText3->SetFont(::Label::Head_13);
|
||||
|
||||
|
||||
m_staticText4 = new Label(this, _L("A desiccant status lower than two bars indicates that desiccant may be inactive. Please change the desiccant.(The bars: higher the better.)"));
|
||||
m_staticText4->SetFont(::Label::Body_13);
|
||||
m_staticText4->SetSize(wxSize(FromDIP(360), -1));
|
||||
m_staticText4->SetMinSize(wxSize(FromDIP(360), -1));
|
||||
m_staticText4->SetMaxSize(wxSize(FromDIP(360), -1));
|
||||
m_staticText4->Wrap(FromDIP(360));
|
||||
m_staticText4->SetSize(wxSize(FromDIP(357), -1));
|
||||
m_staticText4->SetMinSize(wxSize(FromDIP(357), -1));
|
||||
m_staticText4->SetMaxSize(wxSize(FromDIP(357), -1));
|
||||
m_staticText4->Wrap(FromDIP(357));
|
||||
|
||||
m_sizer_tips->Add(m_staticText1, 0, wxALL, 3);
|
||||
m_sizer_tips->Add(m_staticText2, 0, wxALL, 3);
|
||||
m_sizer_tips->Add(m_staticText3, 0, wxALL, 3);
|
||||
m_sizer_tips->Add(m_staticText4, 0, wxALL, 3);
|
||||
m_sizer_tips->Add(m_staticText1, 0, wxLEFT|wxRIGHT, 3);
|
||||
m_sizer_tips->Add(0,0,0,wxTOP,2);
|
||||
m_sizer_tips->Add(m_staticText2, 0, wxLEFT|wxRIGHT, 3);
|
||||
m_sizer_tips->Add(0,0,0,wxTOP,8);
|
||||
m_sizer_tips->Add(m_staticText3, 0, wxLEFT|wxRIGHT, 3);
|
||||
m_sizer_tips->Add(0,0,0,wxTOP,2);
|
||||
m_sizer_tips->Add(m_staticText4, 0, wxLEFT|wxRIGHT, 3);
|
||||
|
||||
|
||||
m_sizer_body->Add(m_sizer_tips, 0, wxEXPAND, 0);
|
||||
|
||||
|
||||
main_sizer->Add(m_sizer_body, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(30));
|
||||
main_sizer->Add(m_sizer_body, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20));
|
||||
|
||||
m_staticText_note = new Label(this, _L("Note: When the lid is open or the desiccant pack is changed, it can take hours or a night to absorb the moisture. Low temperatures also slow down the process. During this time, the indicator may not represent the chamber accurately."));
|
||||
m_staticText4->SetFont(::Label::Body_13);
|
||||
m_staticText_note->SetMinSize(wxSize(FromDIP(536), -1));
|
||||
m_staticText_note->SetMaxSize(wxSize(FromDIP(536), -1));
|
||||
m_staticText_note->Wrap(FromDIP(536));
|
||||
main_sizer->Add(m_staticText_note, 0, wxALL | wxLEFT | wxRIGHT, 34);
|
||||
m_staticText_note->SetMinSize(wxSize(FromDIP(523), -1));
|
||||
m_staticText_note->SetMaxSize(wxSize(FromDIP(523), -1));
|
||||
m_staticText_note->Wrap(FromDIP(523));
|
||||
main_sizer->Add(m_staticText_note, 0, wxALL | wxLEFT | wxRIGHT, 22);
|
||||
|
||||
m_button_confirm = new Button(this, _L("OK"));
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
|
|
@ -1106,4 +1115,382 @@ void MappingContainer::doRender(wxDC& dc)
|
|||
dc.DrawBitmap(ams_mapping_item_container, 0, 0);
|
||||
}
|
||||
|
||||
AmsReplaceMaterialDialog::AmsReplaceMaterialDialog(wxWindow* parent)
|
||||
: DPIDialog(parent, wxID_ANY, _L("Filaments replace"), wxDefaultPosition, wxDefaultSize, wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX)
|
||||
{
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
create();
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
|
||||
void AmsReplaceMaterialDialog::create()
|
||||
{
|
||||
SetSize(wxSize(FromDIP(376), -1));
|
||||
SetMinSize(wxSize(FromDIP(376), -1));
|
||||
SetMaxSize(wxSize(FromDIP(376), -1));
|
||||
|
||||
// set icon for dialog
|
||||
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
SetSizeHints(wxDefaultSize, wxDefaultSize);
|
||||
|
||||
m_main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto m_top_line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
|
||||
m_top_line->SetBackgroundColour(wxColour(166, 169, 170));
|
||||
m_main_sizer->Add(m_top_line, 0, wxEXPAND, 0);
|
||||
|
||||
|
||||
auto m_button_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
StateColor btn_bg_white(std::pair<wxColour, int>(AMS_CONTROL_DISABLE_COLOUR, StateColor::Disabled),
|
||||
std::pair<wxColour, int>(AMS_CONTROL_DISABLE_COLOUR, StateColor::Pressed),
|
||||
std::pair<wxColour, int>(AMS_CONTROL_DEF_BLOCK_BK_COLOUR, StateColor::Hovered),
|
||||
std::pair<wxColour, int>(AMS_CONTROL_WHITE_COLOUR, StateColor::Normal));
|
||||
|
||||
StateColor btn_bd_white(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
|
||||
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
|
||||
|
||||
StateColor btn_text_white(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
|
||||
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
|
||||
|
||||
auto m_button_close = new Button(this, _L("Close"));
|
||||
m_button_close->SetCornerRadius(FromDIP(11));
|
||||
m_button_close->SetBackgroundColor(btn_bg_white);
|
||||
m_button_close->SetBorderColor(btn_bd_white);
|
||||
m_button_close->SetTextColor(btn_text_white);
|
||||
m_button_close->SetFont(Label::Body_13);
|
||||
m_button_close->SetMinSize(wxSize(FromDIP(42), FromDIP(24)));
|
||||
m_button_close->Bind(wxEVT_BUTTON, [this](auto& e) {
|
||||
EndModal(wxCLOSE);
|
||||
});
|
||||
|
||||
m_button_sizer->Add( 0, 0, 1, wxEXPAND, 0 );
|
||||
m_button_sizer->Add(m_button_close, 0, wxALIGN_CENTER, 0);
|
||||
|
||||
|
||||
m_groups_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
m_main_sizer->Add(0,0,0, wxTOP, FromDIP(12));
|
||||
m_main_sizer->Add(m_groups_sizer,0,wxEXPAND|wxLEFT|wxRIGHT, FromDIP(16));
|
||||
m_main_sizer->Add(0,0,0, wxTOP, FromDIP(20));
|
||||
m_main_sizer->Add(m_button_sizer,0,wxEXPAND|wxLEFT|wxRIGHT, FromDIP(16));
|
||||
m_main_sizer->Add(0,0,0, wxTOP, FromDIP(20));
|
||||
|
||||
|
||||
CenterOnParent();
|
||||
SetSizer(m_main_sizer);
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
|
||||
std::vector<bool> AmsReplaceMaterialDialog::GetStatus(unsigned int status)
|
||||
{
|
||||
std::vector<bool> listStatus;
|
||||
bool current = false;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (status & (1 << i)) {
|
||||
current = true;
|
||||
}
|
||||
else {
|
||||
current = false;
|
||||
}
|
||||
listStatus.push_back(current);
|
||||
}
|
||||
return listStatus;
|
||||
}
|
||||
|
||||
void AmsReplaceMaterialDialog::update_machine_obj(MachineObject* obj)
|
||||
{
|
||||
if (obj) {m_obj = obj;}
|
||||
else {return;}
|
||||
|
||||
AmsTray* tray_list[4*4];
|
||||
for (auto i = 0; i < 4*4; i++) {
|
||||
tray_list[i] = nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
for (auto ams_info : obj->amsList) {
|
||||
int ams_id_int = atoi(ams_info.first.c_str()) * 4;
|
||||
|
||||
for (auto tray_info : ams_info.second->trayList) {
|
||||
int tray_id_int = atoi(tray_info.first.c_str());
|
||||
tray_id_int = ams_id_int + tray_id_int;
|
||||
tray_list[tray_id_int] = tray_info.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {}
|
||||
|
||||
//creat group
|
||||
int group_index = 1;
|
||||
for (int filam : m_obj->filam_bak) {
|
||||
auto status_list = GetStatus(filam);
|
||||
|
||||
wxColour group_color;
|
||||
std::string group_material;
|
||||
|
||||
//get color & material
|
||||
for (auto i = 0; i < status_list.size(); i++) {
|
||||
if (status_list[i] && tray_list[i] != nullptr) {
|
||||
group_color = AmsTray::decode_color(tray_list[i]->color);
|
||||
group_material = tray_list[i]->get_display_filament_type();
|
||||
}
|
||||
}
|
||||
|
||||
m_groups_sizer->Add(create_split_line(wxString::Format("%s%d", _L("Group"), group_index), group_color, group_material, status_list), 0, wxEXPAND, 0);
|
||||
m_groups_sizer->Add(0, 0, 0, wxTOP, FromDIP(12));
|
||||
group_index++;
|
||||
}
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
|
||||
wxWindow* AmsReplaceMaterialDialog::create_split_line(wxString gname, wxColour col, wxString material, std::vector<bool> status_list)
|
||||
{
|
||||
wxColour background_color = wxColour(0xF4F4F4);
|
||||
|
||||
if (abs(col.Red() - background_color.Red()) <= 5 &&
|
||||
abs(col.Green() - background_color.Green()) <= 5 &&
|
||||
abs(col.Blue() - background_color.Blue()) <= 5) {
|
||||
background_color = wxColour(0xE6E6E6);
|
||||
}
|
||||
|
||||
auto m_panel_group = new StaticBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
|
||||
m_panel_group->SetCornerRadius(FromDIP(4));
|
||||
m_panel_group->SetBackgroundColor(StateColor(std::pair<wxColour, int>(background_color, StateColor::Normal)));
|
||||
|
||||
m_panel_group->SetSize(wxSize(FromDIP(344), -1));
|
||||
m_panel_group->SetMinSize(wxSize(FromDIP(344), -1));
|
||||
m_panel_group->SetMaxSize(wxSize(FromDIP(344), -1));
|
||||
|
||||
wxBoxSizer* group_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
//group title
|
||||
wxBoxSizer* title_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto group_name = new Label(m_panel_group, gname);
|
||||
group_name->SetFont(::Label::Head_12);
|
||||
|
||||
Button* material_info = new Button(m_panel_group, material);
|
||||
material_info->SetFont(Label::Head_12);
|
||||
material_info->SetCornerRadius(FromDIP(2));
|
||||
material_info->SetBorderColor(background_color);
|
||||
|
||||
if (col.GetLuminance() < 0.5)
|
||||
material_info->SetTextColor(*wxWHITE);
|
||||
else
|
||||
material_info->SetTextColor(0x6B6B6B);
|
||||
|
||||
material_info->SetMinSize(wxSize(-1, FromDIP(24)));
|
||||
material_info->SetBackgroundColor(col);
|
||||
|
||||
|
||||
title_sizer->Add(group_name, 0, wxALIGN_CENTER, 0);
|
||||
title_sizer->Add(0, 0, 0, wxLEFT, FromDIP(10));
|
||||
title_sizer->Add(material_info, 0, wxALIGN_CENTER, 0);
|
||||
|
||||
|
||||
//group item
|
||||
wxGridSizer* grid_Sizer = new wxGridSizer(0, 8, 0, 0);
|
||||
|
||||
for (int i = 0; i < status_list.size(); i++) {
|
||||
if (status_list[i]) {
|
||||
AmsRMItem* amsitem = new AmsRMItem(m_panel_group, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
amsitem->set_color(col);
|
||||
|
||||
//set current tray
|
||||
if (!m_obj->m_tray_now.empty() && m_obj->m_tray_now == std::to_string(i)) {
|
||||
amsitem->set_focus(true);
|
||||
}
|
||||
|
||||
amsitem->set_type(RMTYPE_NORMAL);
|
||||
amsitem->set_index(wxGetApp().transition_tridid(i).ToStdString());
|
||||
amsitem->SetBackgroundColour(background_color);
|
||||
grid_Sizer->Add(amsitem, 0, wxALIGN_CENTER | wxTOP | wxBottom, FromDIP(10));
|
||||
}
|
||||
}
|
||||
|
||||
//add the first tray
|
||||
for (int i = 0; i < status_list.size(); i++) {
|
||||
if (status_list[i]) {
|
||||
AmsRMItem* amsitem = new AmsRMItem(m_panel_group, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
amsitem->set_color(col);
|
||||
amsitem->set_type(RMTYPE_VIRTUAL);
|
||||
amsitem->set_index(wxGetApp().transition_tridid(i).ToStdString());
|
||||
amsitem->SetBackgroundColour(background_color);
|
||||
grid_Sizer->Add(amsitem, 0, wxALIGN_CENTER | wxTOP | wxBottom, FromDIP(10));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
group_sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
group_sizer->Add(title_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(12));
|
||||
group_sizer->Add(grid_Sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(12));
|
||||
group_sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
|
||||
m_panel_group->SetSizer(group_sizer);
|
||||
m_panel_group->Layout();
|
||||
group_sizer->Fit(m_panel_group);
|
||||
return m_panel_group;
|
||||
}
|
||||
|
||||
void AmsReplaceMaterialDialog::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
dc.SetPen(wxColour(0xAC, 0xAC, 0xAC));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0);
|
||||
}
|
||||
|
||||
void AmsReplaceMaterialDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AmsRMItem::AmsRMItem(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size)
|
||||
{
|
||||
wxWindow::Create(parent, id, pos, size);
|
||||
|
||||
SetSize(wxSize(FromDIP(42), FromDIP(32)));
|
||||
SetMinSize(wxSize(FromDIP(42), FromDIP(32)));
|
||||
SetMaxSize(wxSize(FromDIP(42), FromDIP(32)));
|
||||
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
|
||||
Bind(wxEVT_PAINT, &AmsRMItem::paintEvent, this);
|
||||
}
|
||||
|
||||
void AmsRMItem::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void AmsRMItem::render(wxDC& dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxSize size = GetSize();
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 });
|
||||
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AmsRMItem::doRender(wxDC& dc)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
|
||||
if (m_type == RMTYPE_NORMAL) {
|
||||
dc.SetPen(wxPen(m_color, 2));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
}
|
||||
else {
|
||||
dc.SetPen(wxPen(m_color, 2, wxSHORT_DASH));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
}
|
||||
|
||||
//top bottom line
|
||||
dc.DrawLine(FromDIP(0), FromDIP(4), size.x - FromDIP(5), FromDIP(4));
|
||||
dc.DrawLine(FromDIP(0), size.y - FromDIP(4), size.x - FromDIP(5), size.y - FromDIP(4));
|
||||
|
||||
//left right line
|
||||
dc.DrawLine(FromDIP(1), FromDIP(4), FromDIP(1), FromDIP(11));
|
||||
dc.DrawLine(FromDIP(1), FromDIP(22), FromDIP(1), size.y - FromDIP(4));
|
||||
|
||||
dc.DrawLine(size.x - FromDIP(5), FromDIP(4), size.x - FromDIP(5), FromDIP(11));
|
||||
dc.DrawLine(size.x - FromDIP(5), FromDIP(22), size.x - FromDIP(5), size.y - FromDIP(4));
|
||||
|
||||
//delta
|
||||
dc.DrawLine(FromDIP(0), FromDIP(11), FromDIP(5), size.y / 2);
|
||||
dc.DrawLine(FromDIP(0), FromDIP(22), FromDIP(5), size.y / 2);
|
||||
|
||||
dc.DrawLine(size.x - FromDIP(5), FromDIP(11), size.x - FromDIP(1), size.y / 2);
|
||||
dc.DrawLine(size.x - FromDIP(5), FromDIP(22), size.x - FromDIP(1), size.y / 2);
|
||||
|
||||
|
||||
if (m_focus) {
|
||||
dc.SetPen(wxPen(wxColour(0x00AE42), 2));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawLine(FromDIP(0), FromDIP(1), size.x - FromDIP(5), FromDIP(1));
|
||||
dc.DrawLine(FromDIP(0), size.y - FromDIP(1), size.x - FromDIP(5), size.y - FromDIP(1));
|
||||
}
|
||||
|
||||
if (m_selected) {
|
||||
}
|
||||
|
||||
auto tsize = dc.GetMultiLineTextExtent(m_index);
|
||||
auto tpot = wxPoint((size.x - tsize.x) / 2 - FromDIP(2), (size.y - tsize.y) / 2 + FromDIP(2));
|
||||
dc.SetTextForeground(wxColour(0x6B6B6B));
|
||||
dc.SetFont(::Label::Head_12);
|
||||
dc.DrawText(m_index, tpot);
|
||||
}
|
||||
|
||||
AmsRMArrow::AmsRMArrow(wxWindow* parent)
|
||||
{
|
||||
|
||||
wxWindow::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
Bind(wxEVT_PAINT, &AmsRMArrow::paintEvent, this);
|
||||
|
||||
m_bitmap_left = ScalableBitmap(this, "replace_arrow_left", 7);
|
||||
m_bitmap_right = ScalableBitmap(this, "replace_arrow_right", 7);
|
||||
m_bitmap_down = ScalableBitmap(this, "replace_arrow_down", 7);
|
||||
|
||||
|
||||
SetSize(wxSize(FromDIP(16), FromDIP(32)));
|
||||
SetMinSize(wxSize(FromDIP(16), FromDIP(32)));
|
||||
SetMaxSize(wxSize(FromDIP(16), FromDIP(32)));
|
||||
}
|
||||
|
||||
void AmsRMArrow::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void AmsRMArrow::render(wxDC& dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxSize size = GetSize();
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 });
|
||||
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AmsRMArrow::doRender(wxDC& dc)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
|
||||
dc.SetPen(wxPen(wxColour(0, 174, 66)));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
|
||||
|
||||
dc.SetPen(wxPen(wxColour(0xACACAC)));
|
||||
dc.SetBrush(wxBrush(wxColour(0xACACAC)));
|
||||
dc.DrawCircle(size.x / 2, size.y / 2, FromDIP(7));
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ public:
|
|||
MaterialItem(wxWindow *parent,wxColour mcolour, wxString mname);
|
||||
~MaterialItem();
|
||||
|
||||
wxPanel* m_main_panel;
|
||||
wxColour m_material_coloul;
|
||||
wxString m_material_name;
|
||||
|
||||
|
|
@ -129,7 +130,6 @@ class AmsMapingPopup : public PopupWindow
|
|||
{
|
||||
public:
|
||||
AmsMapingPopup(wxWindow *parent);
|
||||
wxString format_text(wxString &m_msg);
|
||||
~AmsMapingPopup(){};
|
||||
|
||||
wxStaticText * m_warning_text{nullptr};
|
||||
|
|
@ -143,7 +143,9 @@ public:
|
|||
std::string m_tag_material;
|
||||
wxBoxSizer *m_sizer_main{nullptr};
|
||||
wxBoxSizer *m_sizer_list{nullptr};
|
||||
wxWindow *m_parent_item{nullptr};
|
||||
|
||||
wxString format_text(wxString &m_msg);
|
||||
void update_materials_list(std::vector<std::string> list);
|
||||
void set_tag_texture(std::string texture);
|
||||
void update_ams_data(std::map<std::string, Ams *> amsList);
|
||||
|
|
@ -155,6 +157,7 @@ public:
|
|||
virtual void OnDismiss() wxOVERRIDE;
|
||||
virtual bool ProcessLeftDown(wxMouseEvent &event) wxOVERRIDE;
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
void set_parent_item(wxWindow* item) {m_parent_item = item;};
|
||||
std::vector<TrayData> parse_ams_mapping(std::map<std::string, Ams*> amsList);
|
||||
};
|
||||
|
||||
|
|
@ -239,6 +242,75 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class AmsReplaceMaterialDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
AmsReplaceMaterialDialog(wxWindow* parent);
|
||||
~AmsReplaceMaterialDialog() {};
|
||||
|
||||
public:
|
||||
wxWindow* create_split_line(wxString gname, wxColour col, wxString material, std::vector<bool> status_list);
|
||||
void create();
|
||||
void update_machine_obj(MachineObject* obj);
|
||||
void on_left_down(wxMouseEvent& evt);
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
std::vector<bool> GetStatus(unsigned int status);
|
||||
|
||||
public:
|
||||
wxBoxSizer* m_main_sizer{nullptr};
|
||||
wxBoxSizer* m_groups_sizer{nullptr};
|
||||
|
||||
MachineObject* m_obj{nullptr};
|
||||
};
|
||||
|
||||
|
||||
enum RMTYPE {
|
||||
RMTYPE_NORMAL = 0,
|
||||
RMTYPE_VIRTUAL = 1,
|
||||
};
|
||||
|
||||
class AmsRMItem : public wxWindow
|
||||
{
|
||||
public:
|
||||
AmsRMItem(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
|
||||
~AmsRMItem() {};
|
||||
|
||||
public:
|
||||
void set_color(wxColour col) {m_color = col;};
|
||||
void set_type(RMTYPE type) {m_type = type;};
|
||||
void set_index(std::string index) {m_index = index;};
|
||||
void set_focus(bool focus) {m_focus = focus;};
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void render(wxDC& dc);
|
||||
void doRender(wxDC& dc);
|
||||
|
||||
private:
|
||||
RMTYPE m_type;
|
||||
wxColour m_color;
|
||||
std::string m_index;
|
||||
bool m_focus = false;
|
||||
bool m_selected = false;
|
||||
};
|
||||
|
||||
class AmsRMArrow : public wxWindow
|
||||
{
|
||||
public:
|
||||
AmsRMArrow(wxWindow* parent);
|
||||
~AmsRMArrow() {};
|
||||
|
||||
public:
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void render(wxDC& dc);
|
||||
void doRender(wxDC& dc);
|
||||
|
||||
private:
|
||||
ScalableBitmap m_bitmap_left;
|
||||
ScalableBitmap m_bitmap_right;
|
||||
ScalableBitmap m_bitmap_down;
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(EVT_SET_FINISH_MAPPING, wxCommandEvent);
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
|
|
|||
|
|
@ -1034,7 +1034,6 @@ void AuxiliaryPanel::Reload(wxString aux_path)
|
|||
auto iter = m_paths_list.find(folder.ToStdString());
|
||||
auto file_path_str = fs::path(file_path.c_str());
|
||||
|
||||
|
||||
if (iter != m_paths_list.end()) {
|
||||
m_paths_list[folder.ToStdString()].push_back(file_path_str);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -128,6 +128,11 @@ void BBLStatusBar::clear_percent()
|
|||
|
||||
}
|
||||
|
||||
void BBLStatusBar::show_networking_test(wxString msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BBLStatusBar::show_progress(bool show)
|
||||
{
|
||||
if (show) {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public:
|
|||
int get_range() const override;
|
||||
void set_range(int = 100) override;
|
||||
void clear_percent() override;
|
||||
void show_networking_test(wxString msg) override;
|
||||
void show_progress(bool);
|
||||
void start_busy(int = 100);
|
||||
void stop_busy();
|
||||
|
|
|
|||
|
|
@ -97,6 +97,11 @@ void BBLStatusBarBind::clear_percent()
|
|||
|
||||
}
|
||||
|
||||
void BBLStatusBarBind::show_networking_test(wxString msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BBLStatusBarBind::show_progress(bool show)
|
||||
{
|
||||
if (show) {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ public:
|
|||
int get_range() const override;
|
||||
void set_range(int = 100) override;
|
||||
void clear_percent() override;
|
||||
void show_networking_test(wxString msg) override;
|
||||
void show_progress(bool);
|
||||
void start_busy(int = 100);
|
||||
void stop_busy();
|
||||
|
|
|
|||
|
|
@ -29,23 +29,18 @@ BBLStatusBarSend::BBLStatusBarSend(wxWindow *parent, int id)
|
|||
m_status_text = new wxStaticText(m_self, wxID_ANY, wxEmptyString);
|
||||
m_status_text->SetForegroundColour(wxColour(107, 107, 107));
|
||||
m_status_text->SetFont(::Label::Body_13);
|
||||
m_status_text->SetSize(wxSize(m_self->FromDIP(280), m_self->FromDIP(46)));
|
||||
m_status_text->SetMaxSize(wxSize(m_self->FromDIP(280), m_self->FromDIP(46)));
|
||||
m_status_text->SetSize(wxSize(m_self->FromDIP(300), m_self->FromDIP(46)));
|
||||
m_status_text->SetMaxSize(wxSize(m_self->FromDIP(300), m_self->FromDIP(46)));
|
||||
|
||||
m_prog = new wxGauge(m_self, wxID_ANY, 100, wxDefaultPosition, wxSize(-1, m_self->FromDIP(6)), wxGA_HORIZONTAL);
|
||||
m_prog->SetMinSize(wxSize(m_self->FromDIP(300),m_self->FromDIP(6)));
|
||||
m_prog->SetValue(0);
|
||||
|
||||
/* block_left = new wxWindow(m_prog, wxID_ANY, wxPoint(0, 0), wxSize(2, m_prog->GetSize().GetHeight() * 2));
|
||||
block_left->SetBackgroundColour(wxColour(255, 255, 255));
|
||||
block_right = new wxWindow(m_prog, wxID_ANY, wxPoint(m_prog->GetSize().GetWidth() - 2, 0), wxSize(2, m_prog->GetSize().GetHeight() * 2));
|
||||
block_right->SetBackgroundColour(wxColour(255, 255, 255));*/
|
||||
|
||||
m_sizer_bottom->Add(m_prog, 1, wxALIGN_CENTER, 0);
|
||||
|
||||
StateColor btn_bd_white(std::pair<wxColour, int>(*wxWHITE, StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
|
||||
StateColor btn_bd_white(std::pair<wxColour, int>(*wxWHITE, StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
|
||||
|
||||
m_cancelbutton = new Button(m_self, _L("Cancel"));
|
||||
m_cancelbutton->SetMinSize(wxSize(m_self->FromDIP(64), m_self->FromDIP(24)));
|
||||
m_cancelbutton->SetMinSize(wxSize(m_self->FromDIP(58), m_self->FromDIP(22)));
|
||||
m_cancelbutton->SetMaxSize(wxSize(m_self->FromDIP(58), m_self->FromDIP(22)));
|
||||
m_cancelbutton->SetBackgroundColor(wxColour(255, 255, 255));
|
||||
m_cancelbutton->SetBorderColor(btn_bd_white);
|
||||
m_cancelbutton->SetCornerRadius(m_self->FromDIP(12));
|
||||
|
|
@ -60,11 +55,19 @@ BBLStatusBarSend::BBLStatusBarSend(wxWindow *parent, int id)
|
|||
m_stext_percent->SetForegroundColour(wxColour(107, 107, 107));
|
||||
m_stext_percent->SetFont(::Label::Body_13);
|
||||
m_stext_percent->Wrap(-1);
|
||||
m_sizer_bottom->Add(m_stext_percent, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 10);
|
||||
|
||||
m_hyperlink = new Label(m_self, _L("Check the status of current system services"));
|
||||
m_hyperlink->SetForegroundColour(0x00AE42);
|
||||
m_hyperlink->SetFont(::Label::Body_12);
|
||||
m_hyperlink->Hide();
|
||||
m_sizer_bottom->Add(m_prog, 1, wxALIGN_CENTER, 0);
|
||||
m_sizer_bottom->Add(m_stext_percent, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 10);
|
||||
m_sizer_bottom->Add(m_hyperlink, 0, wxALIGN_CENTER, 10);
|
||||
m_sizer_bottom->Add(0, 0, 1, wxEXPAND, 0);
|
||||
m_sizer_bottom->Add(m_cancelbutton, 0, wxALIGN_CENTER, 0);
|
||||
|
||||
m_sizer_body->Add(m_status_text, 0, 0, 0);
|
||||
|
||||
m_sizer_body->Add(m_status_text, 0, wxALL, 0);
|
||||
m_sizer_body->Add(0, 0, 0, wxTOP, 1);
|
||||
m_sizer_body->Add(m_sizer_bottom, 1, wxEXPAND, 0);
|
||||
|
||||
|
|
@ -123,6 +126,53 @@ void BBLStatusBarSend::clear_percent()
|
|||
m_cancelbutton->Hide();
|
||||
}
|
||||
|
||||
void BBLStatusBarSend::show_networking_test(wxString msg)
|
||||
{
|
||||
std::string url;
|
||||
std::string country_code = Slic3r::GUI::wxGetApp().app_config->get_country_code();
|
||||
|
||||
|
||||
if (country_code == "US") {
|
||||
url = "https://status.bambulab.com";
|
||||
}
|
||||
else if (country_code == "CN") {
|
||||
url = "https://status.bambulab.cn";
|
||||
}
|
||||
else if (country_code == "ENV_CN_DEV") {
|
||||
url = "https://status.bambu-lab.com";
|
||||
}
|
||||
else if (country_code == "ENV_CN_QA") {
|
||||
url = "https://status.bambu-lab.com";
|
||||
}
|
||||
else if (country_code == "ENV_CN_PRE") {
|
||||
url = "https://status.bambu-lab.com";
|
||||
}
|
||||
else {
|
||||
url = "https://status.bambu-lab.com";
|
||||
}
|
||||
|
||||
|
||||
m_hyperlink->Bind(wxEVT_LEFT_DOWN, [this, url](auto& e) {
|
||||
wxLaunchDefaultBrowser(url);
|
||||
});
|
||||
|
||||
m_hyperlink->Bind(wxEVT_ENTER_WINDOW, [this, url](auto& e) {
|
||||
m_hyperlink->SetCursor(wxCURSOR_HAND);
|
||||
});
|
||||
|
||||
m_hyperlink->Bind(wxEVT_LEAVE_WINDOW, [this, url](auto& e) {
|
||||
m_hyperlink->SetCursor(wxCURSOR_ARROW);
|
||||
});
|
||||
|
||||
set_status_text(msg);
|
||||
m_prog->Hide();
|
||||
m_stext_percent->Hide();
|
||||
m_hyperlink->Show();
|
||||
m_cancelbutton->Show();
|
||||
m_self->Layout();
|
||||
m_sizer->Layout();
|
||||
}
|
||||
|
||||
void BBLStatusBarSend::show_progress(bool show)
|
||||
{
|
||||
if (show) {
|
||||
|
|
@ -234,7 +284,7 @@ void BBLStatusBarSend::set_status_text(const wxString& txt)
|
|||
//auto txtss = "The printing project is being uploaded... 25%%";
|
||||
//m_status_text->SetLabelText(txtss);
|
||||
wxString str;
|
||||
format_text(m_status_text, m_self->FromDIP(280), txt, str);
|
||||
format_text(m_status_text, m_self->FromDIP(300), txt, str);
|
||||
m_status_text->SetLabelText(str);
|
||||
m_self->Layout();
|
||||
//if (is_english_text(str)) m_status_text->Wrap(m_self->FromDIP(280));
|
||||
|
|
@ -281,9 +331,13 @@ bool BBLStatusBarSend::update_status(wxString &msg, bool &was_cancel, int percen
|
|||
|
||||
void BBLStatusBarSend::reset()
|
||||
{
|
||||
m_hyperlink->Hide();
|
||||
m_prog->Show();
|
||||
m_stext_percent->Show();
|
||||
m_cancelbutton->Show();
|
||||
set_status_text("");
|
||||
m_was_cancelled = false;
|
||||
|
||||
set_status_text("");
|
||||
set_progress(0);
|
||||
set_percent_text(wxString::Format("%d%%", 0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <string>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <wx/hyperlink.h>
|
||||
|
||||
#include "Jobs/ProgressIndicator.hpp"
|
||||
#include "Widgets/Label.hpp"
|
||||
|
|
@ -29,6 +30,7 @@ class BBLStatusBarSend : public ProgressIndicator
|
|||
{
|
||||
wxPanel * m_self; // we cheat! It should be the base class but: perl!
|
||||
wxGauge * m_prog;
|
||||
Label * m_hyperlink;
|
||||
Button * m_cancelbutton;
|
||||
wxStaticText *m_status_text;
|
||||
wxStaticText *m_stext_percent;
|
||||
|
|
@ -49,6 +51,7 @@ public:
|
|||
int get_range() const override;
|
||||
void set_range(int = 100) override;
|
||||
void clear_percent() override;
|
||||
void show_networking_test(wxString msg) override;
|
||||
void show_progress(bool);
|
||||
void start_busy(int = 100);
|
||||
void stop_busy();
|
||||
|
|
|
|||
|
|
@ -763,7 +763,6 @@ void BackgroundSlicingProcess::finalize_gcode()
|
|||
// collide with the G-code viewer memory mapping of the unprocessed G-code. G-code viewer maps unprocessed G-code, because m_gcode_result
|
||||
// is calculated for the unprocessed G-code and it references lines in the memory mapped G-code file by line numbers.
|
||||
// export_path may be changed by the post-processing script as well if the post processing script decides so, see GH #6042.
|
||||
//BBS: don't support running post process scripts
|
||||
bool post_processed = run_post_process_scripts(output_path, true, "File", export_path, m_fff_print->full_print_config());
|
||||
auto remove_post_processed_temp_file = [post_processed, &output_path]() {
|
||||
if (post_processed)
|
||||
|
|
|
|||
|
|
@ -262,8 +262,13 @@ namespace GUI {
|
|||
//check dev_id
|
||||
if (m_machine_info->dev_id.empty()) return;
|
||||
|
||||
// update ota version
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (agent)
|
||||
agent->track_update_property("dev_ota_version", m_machine_info->get_ota_version());
|
||||
|
||||
m_simplebook->SetSelection(0);
|
||||
m_bind_job = std::make_shared<BindJob>(m_status_bar, wxGetApp().plater(), m_machine_info->dev_id, m_machine_info->dev_ip);
|
||||
m_bind_job = std::make_shared<BindJob>(m_status_bar, wxGetApp().plater(), m_machine_info->dev_id, m_machine_info->dev_ip, m_machine_info->bind_sec_link);
|
||||
m_bind_job->set_event_handle(this);
|
||||
m_bind_job->start();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ double Camera::FrustrumMinZRange = 50.0;
|
|||
double Camera::FrustrumMinNearZ = 100.0;
|
||||
double Camera::FrustrumZMargin = 10.0;
|
||||
double Camera::MaxFovDeg = 60.0;
|
||||
double Camera::ZoomUnit = 0.1;
|
||||
|
||||
std::string Camera::get_type_as_string() const
|
||||
{
|
||||
|
|
@ -52,6 +53,12 @@ void Camera::select_next_type()
|
|||
set_type((EType)next);
|
||||
}
|
||||
|
||||
void Camera::translate(const Vec3d& displacement) {
|
||||
if (!displacement.isApprox(Vec3d::Zero())) {
|
||||
m_view_matrix.translate(-displacement);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::set_target(const Vec3d& target)
|
||||
{
|
||||
//BBS do not check validation
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ struct Camera
|
|||
static double FrustrumMinNearZ;
|
||||
static double FrustrumZMargin;
|
||||
static double MaxFovDeg;
|
||||
static double ZoomUnit;
|
||||
|
||||
enum class EType : unsigned char
|
||||
{
|
||||
|
|
@ -67,6 +68,7 @@ public:
|
|||
|
||||
void enable_update_config_on_type_change(bool enable) { m_update_config_on_type_change_enabled = enable; }
|
||||
|
||||
void translate(const Vec3d& displacement);
|
||||
const Vec3d& get_target() const { return m_target; }
|
||||
void set_target(const Vec3d& target);
|
||||
|
||||
|
|
@ -76,7 +78,7 @@ public:
|
|||
|
||||
double get_zoom() const { return m_zoom; }
|
||||
double get_inv_zoom() const { assert(m_zoom != 0.0); return 1.0 / m_zoom; }
|
||||
void update_zoom(double delta_zoom) { set_zoom(m_zoom / (1.0 - std::max(std::min(delta_zoom, 4.0), -4.0) * 0.1)); }
|
||||
void update_zoom(double delta_zoom) { set_zoom(m_zoom / (1.0 - std::max(std::min(delta_zoom, 4.0), -4.0) * ZoomUnit)); }
|
||||
void set_zoom(double zoom);
|
||||
|
||||
const BoundingBoxf3& get_scene_box() const { return m_scene_box; }
|
||||
|
|
|
|||
131
src/slic3r/GUI/CameraUtils.cpp
Normal file
131
src/slic3r/GUI/CameraUtils.cpp
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#include "CameraUtils.hpp"
|
||||
#include <igl/project.h> // projecting points
|
||||
#include <igl/unproject.h>
|
||||
|
||||
#include "slic3r/GUI/3DScene.hpp" // GLVolume
|
||||
#include "libslic3r/Geometry/ConvexHull.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace GUI;
|
||||
|
||||
Points CameraUtils::project(const Camera & camera,
|
||||
const std::vector<Vec3d> &points)
|
||||
{
|
||||
Vec4i viewport(camera.get_viewport().data());
|
||||
|
||||
// Convert our std::vector to Eigen dynamic matrix.
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::DontAlign>
|
||||
pts(points.size(), 3);
|
||||
for (size_t i = 0; i < points.size(); ++i)
|
||||
pts.block<1, 3>(i, 0) = points[i];
|
||||
|
||||
// Get the projections.
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::DontAlign> projections;
|
||||
igl::project(pts, camera.get_view_matrix().matrix(),
|
||||
camera.get_projection_matrix().matrix(), viewport, projections);
|
||||
|
||||
Points result;
|
||||
result.reserve(points.size());
|
||||
int window_height = viewport[3];
|
||||
|
||||
// convert to points --> loss precision
|
||||
for (int i = 0; i < projections.rows(); ++i) {
|
||||
double x = projections(i, 0);
|
||||
double y = projections(i, 1);
|
||||
// opposit direction o Y
|
||||
result.emplace_back(x, window_height - y);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Point CameraUtils::project(const Camera &camera, const Vec3d &point)
|
||||
{
|
||||
// IMPROVE: do it faster when you need it (inspire in project multi point)
|
||||
return project(camera, std::vector{point}).front();
|
||||
}
|
||||
|
||||
Slic3r::Polygon CameraUtils::create_hull2d(const Camera & camera,
|
||||
const GLVolume &volume)
|
||||
{
|
||||
std::vector<Vec3d> vertices;
|
||||
const TriangleMesh *hull = volume.convex_hull();
|
||||
if (hull != nullptr) {
|
||||
const indexed_triangle_set &its = hull->its;
|
||||
vertices.reserve(its.vertices.size());
|
||||
// cast vector
|
||||
for (const Vec3f &vertex : its.vertices)
|
||||
vertices.emplace_back(vertex.cast<double>());
|
||||
} else {
|
||||
// Negative volume doesn't have convex hull so use bounding box
|
||||
auto bb = volume.bounding_box();
|
||||
Vec3d &min = bb.min;
|
||||
Vec3d &max = bb.max;
|
||||
vertices = {min,
|
||||
Vec3d(min.x(), min.y(), max.z()),
|
||||
Vec3d(min.x(), max.y(), min.z()),
|
||||
Vec3d(min.x(), max.y(), max.z()),
|
||||
Vec3d(max.x(), min.y(), min.z()),
|
||||
Vec3d(max.x(), min.y(), max.z()),
|
||||
Vec3d(max.x(), max.y(), min.z()),
|
||||
max};
|
||||
}
|
||||
|
||||
const Transform3d &trafoMat =
|
||||
volume.get_instance_transformation().get_matrix() *
|
||||
volume.get_volume_transformation().get_matrix();
|
||||
for (Vec3d &vertex : vertices)
|
||||
vertex = trafoMat * vertex.cast<double>();
|
||||
|
||||
Points vertices_2d = project(camera, vertices);
|
||||
return Geometry::convex_hull(vertices_2d);
|
||||
}
|
||||
|
||||
void CameraUtils::ray_from_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction) {
|
||||
switch (camera.get_type()) {
|
||||
case Camera::EType::Ortho: return ray_from_ortho_screen_pos(camera, position, point, direction);
|
||||
case Camera::EType::Perspective: return ray_from_persp_screen_pos(camera, position, point, direction);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
Vec3d CameraUtils::screen_point(const Camera &camera, const Vec2d &position)
|
||||
{
|
||||
double height = camera.get_viewport().data()[3];
|
||||
// Y coordinate has opposit direction
|
||||
return Vec3d(position.x(), height - position.y(), 0.);
|
||||
}
|
||||
|
||||
void CameraUtils::ray_from_ortho_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction)
|
||||
{
|
||||
assert(camera.get_type() == Camera::EType::Ortho);
|
||||
Matrix4d modelview = camera.get_view_matrix().matrix();
|
||||
Matrix4d projection = camera.get_projection_matrix().matrix();
|
||||
Vec4i viewport(camera.get_viewport().data());
|
||||
igl::unproject(screen_point(camera,position), modelview, projection, viewport, point);
|
||||
direction = camera.get_dir_forward();
|
||||
}
|
||||
void CameraUtils::ray_from_persp_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction)
|
||||
{
|
||||
assert(camera.get_type() == Camera::EType::Perspective);
|
||||
Matrix4d modelview = camera.get_view_matrix().matrix();
|
||||
Matrix4d projection = camera.get_projection_matrix().matrix();
|
||||
Vec4i viewport(camera.get_viewport().data());
|
||||
igl::unproject(screen_point(camera, position), modelview, projection, viewport, point);
|
||||
direction = point - camera.get_position();
|
||||
}
|
||||
|
||||
Vec2d CameraUtils::get_z0_position(const Camera &camera, const Vec2d & coor)
|
||||
{
|
||||
Vec3d p0, dir;
|
||||
ray_from_screen_pos(camera, coor, p0, dir);
|
||||
|
||||
// is approx zero
|
||||
if ((fabs(dir.z()) - 1e-4) < 0)
|
||||
return Vec2d(std::numeric_limits<double>::max(),
|
||||
std::numeric_limits<double>::max());
|
||||
|
||||
// find position of ray cross plane(z = 0)
|
||||
double t = p0.z() / dir.z();
|
||||
Vec3d p = p0 - t * dir;
|
||||
return Vec2d(p.x(), p.y());
|
||||
}
|
||||
69
src/slic3r/GUI/CameraUtils.hpp
Normal file
69
src/slic3r/GUI/CameraUtils.hpp
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef slic3r_CameraUtils_hpp_
|
||||
#define slic3r_CameraUtils_hpp_
|
||||
|
||||
#include "Camera.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
namespace Slic3r {
|
||||
class GLVolume;
|
||||
}
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
/// <summary>
|
||||
/// Help divide camera data and camera functions
|
||||
/// This utility work with camera data by static funtions
|
||||
/// </summary>
|
||||
class CameraUtils
|
||||
{
|
||||
public:
|
||||
CameraUtils() = delete; // only static functions
|
||||
|
||||
/// <summary>
|
||||
/// Project point throw camera to 2d coordinate into imgui window
|
||||
/// </summary>
|
||||
/// <param name="camera">Projection params</param>
|
||||
/// <param name="points">Point to project.</param>
|
||||
/// <returns>projected points by camera into coordinate of camera.
|
||||
/// x(from left to right), y(from top to bottom)</returns>
|
||||
static Points project(const Camera& camera, const std::vector<Vec3d> &points);
|
||||
static Point project(const Camera& camera, const Vec3d &point);
|
||||
|
||||
/// <summary>
|
||||
/// Create hull around GLVolume in 2d space of camera
|
||||
/// </summary>
|
||||
/// <param name="camera">Projection params</param>
|
||||
/// <param name="volume">Outline by 3d object</param>
|
||||
/// <returns>Polygon around object</returns>
|
||||
static Polygon create_hull2d(const Camera &camera, const GLVolume &volume);
|
||||
|
||||
/// <summary>
|
||||
/// Create ray(point and direction) for screen coordinate
|
||||
/// </summary>
|
||||
/// <param name="camera">Definition of camera</param>
|
||||
/// <param name="position">Position on screen(aka mouse position) </param>
|
||||
/// <param name="point">OUT start of ray</param>
|
||||
/// <param name="direction">OUT direction of ray</param>
|
||||
static void ray_from_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction);
|
||||
static void ray_from_ortho_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction);
|
||||
static void ray_from_persp_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction);
|
||||
|
||||
/// <summary>
|
||||
/// Unproject mouse coordinate to get position in space where z coor is zero
|
||||
/// Platter surface should be in z == 0
|
||||
/// </summary>
|
||||
/// <param name="camera">Projection params</param>
|
||||
/// <param name="coor">Mouse position</param>
|
||||
/// <returns>Position on platter under mouse</returns>
|
||||
static Vec2d get_z0_position(const Camera &camera, const Vec2d &coor);
|
||||
|
||||
/// <summary>
|
||||
/// Create 3d screen point from 2d position
|
||||
/// </summary>
|
||||
/// <param name="camera">Define camera viewport</param>
|
||||
/// <param name="position">Position on screen(aka mouse position)</param>
|
||||
/// <returns>Point represented screen coor in 3d</returns>
|
||||
static Vec3d screen_point(const Camera &camera, const Vec2d &position);
|
||||
|
||||
};
|
||||
} // Slic3r::GUI
|
||||
|
||||
#endif /* slic3r_CameraUtils_hpp_ */
|
||||
|
|
@ -283,7 +283,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
|||
! config->opt_bool("detect_thin_wall") &&
|
||||
config->opt_enum<TimelapseType>("timelapse_type") == TimelapseType::tlTraditional))
|
||||
{
|
||||
wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0 and timelapse type is traditional"));
|
||||
wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0 and timelapse type is traditional."));
|
||||
if (is_global_config)
|
||||
msg_text += "\n\n" + _(L("Change these settings automatically? \n"
|
||||
"Yes - Change these settings and enable spiral mode automatically\n"
|
||||
|
|
@ -322,6 +322,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
|||
}
|
||||
|
||||
//BBS
|
||||
/*
|
||||
if (config->opt_enum<PerimeterGeneratorType>("wall_generator") == PerimeterGeneratorType::Arachne &&
|
||||
config->opt_bool("overhang_speed_classic"))
|
||||
{
|
||||
|
|
@ -350,7 +351,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
|||
}
|
||||
is_msg_dlg_already_exist = false;
|
||||
}
|
||||
|
||||
*/
|
||||
// BBS
|
||||
int filament_cnt = wxGetApp().preset_bundle->filament_presets.size();
|
||||
#if 0
|
||||
|
|
@ -606,7 +607,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
"bridge_no_support", "max_bridge_length", "support_top_z_distance", "support_bottom_z_distance",
|
||||
//BBS: add more support params to dependent of enable_support
|
||||
"support_type", "support_on_build_plate_only", "support_critical_regions_only",
|
||||
"support_object_xy_distance", "independent_support_layer_height"})
|
||||
"support_object_xy_distance"/*, "independent_support_layer_height"*/})
|
||||
toggle_field(el, have_support_material);
|
||||
toggle_field("support_threshold_angle", have_support_material && is_auto(support_type));
|
||||
//toggle_field("support_closing_radius", have_support_material && support_style == smsSnug);
|
||||
|
|
@ -663,6 +664,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
for (auto el : {"flush_into_infill", "flush_into_support", "flush_into_objects"})
|
||||
toggle_field(el, have_prime_tower);
|
||||
|
||||
// BBS: MusangKing - Hide "Independent support layer height" option
|
||||
toggle_line("independent_support_layer_height", have_support_material && !have_prime_tower);
|
||||
|
||||
bool have_avoid_crossing_perimeters = config->opt_bool("reduce_crossing_wall");
|
||||
toggle_line("max_travel_detour_distance", have_avoid_crossing_perimeters);
|
||||
|
||||
|
|
@ -678,10 +682,6 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
for (auto el : { "fuzzy_skin_thickness", "fuzzy_skin_point_distance"})
|
||||
toggle_line(el, has_fuzzy_skin);
|
||||
|
||||
// C11 printer is not support smooth timelapse
|
||||
std::string str_preset_type = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||
toggle_field("timelapse_type", str_preset_type != "C11");
|
||||
|
||||
bool have_arachne = config->opt_enum<PerimeterGeneratorType>("wall_generator") == PerimeterGeneratorType::Arachne;
|
||||
for (auto el : { "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
|
||||
"min_feature_size", "min_bead_width", "wall_distribution_count" })
|
||||
|
|
|
|||
|
|
@ -186,9 +186,9 @@ bool AmsTray::is_unset_third_filament()
|
|||
std::string AmsTray::get_display_filament_type()
|
||||
{
|
||||
if (type == "PLA-S")
|
||||
return "Support W";
|
||||
return "Sup.PLA";
|
||||
else if (type == "PA-S")
|
||||
return "Support G";
|
||||
return "Sup.PA";
|
||||
else
|
||||
return type;
|
||||
return type;
|
||||
|
|
@ -196,7 +196,11 @@ std::string AmsTray::get_display_filament_type()
|
|||
|
||||
std::string AmsTray::get_filament_type()
|
||||
{
|
||||
if (type == "Support W") {
|
||||
if (type == "Sup.PLA") {
|
||||
return "PLA-S";
|
||||
} else if (type == "Sup.PA") {
|
||||
return "PA-S";
|
||||
} else if (type == "Support W") {
|
||||
return "PLA-S";
|
||||
} else if (type == "Support G") {
|
||||
return "PA-S";
|
||||
|
|
@ -556,9 +560,19 @@ AmsTray *MachineObject::get_curr_tray()
|
|||
Ams* curr_ams = get_curr_Ams();
|
||||
if (!curr_ams) return nullptr;
|
||||
|
||||
auto it = curr_ams->trayList.find(m_tray_now);
|
||||
if (it != curr_ams->trayList.end())
|
||||
return it->second;
|
||||
try {
|
||||
int tray_index = atoi(m_tray_now.c_str());
|
||||
int ams_index = atoi(curr_ams->id.c_str());
|
||||
|
||||
std::string tray_now_index = std::to_string(tray_index - ams_index * 4);
|
||||
auto it = curr_ams->trayList.find(tray_now_index);
|
||||
if (it != curr_ams->trayList.end())
|
||||
return it->second;
|
||||
}
|
||||
catch (...) {
|
||||
;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -1369,10 +1383,18 @@ void MachineObject::parse_version_func()
|
|||
is_support_ai_monitoring = true;
|
||||
is_support_ams_humidity = true;
|
||||
}
|
||||
local_use_ssl = ota_version->second.sw_ver.compare("01.03.01.04") >= 0;
|
||||
if (firmware_type == PrinterFirmwareType::FIRMWARE_TYPE_ENGINEER)
|
||||
local_use_ssl = false;
|
||||
else {
|
||||
local_use_ssl = ota_version->second.sw_ver.compare("01.03.01.04") >= 0;
|
||||
}
|
||||
}
|
||||
} else if (printer_type == "C11") {
|
||||
local_use_ssl = true;
|
||||
if (firmware_type == PrinterFirmwareType::FIRMWARE_TYPE_ENGINEER)
|
||||
local_use_ssl = false;
|
||||
else {
|
||||
local_use_ssl = true;
|
||||
}
|
||||
is_cloud_print_only = true;
|
||||
if (ota_version != module_vers.end()) {
|
||||
is_support_send_to_sdcard = ota_version->second.sw_ver.compare("01.02.00.00") >= 0;
|
||||
|
|
@ -1383,6 +1405,14 @@ void MachineObject::parse_version_func()
|
|||
}
|
||||
}
|
||||
|
||||
bool MachineObject::is_studio_cmd(int sequence_id)
|
||||
{
|
||||
if (sequence_id >= START_SEQ_ID && sequence_id < END_SEQ_ID) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int MachineObject::command_get_version(bool with_retry)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "command_get_version";
|
||||
|
|
@ -1433,6 +1463,18 @@ int MachineObject::command_pushing(std::string cmd)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int MachineObject::command_clean_print_error(std::string subtask_id, int print_error)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "command_clean_print_error, id = " << subtask_id;
|
||||
json j;
|
||||
j["print"]["command"] = "clean_print_error";
|
||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
j["print"]["subtask_id"] = subtask_id;
|
||||
j["print"]["print_error"] = print_error;
|
||||
|
||||
return this->publish_json(j.dump());
|
||||
}
|
||||
|
||||
int MachineObject::command_upgrade_confirm()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "command_upgrade_confirm";
|
||||
|
|
@ -1850,8 +1892,8 @@ int MachineObject::command_start_calibration(bool vibration, bool bed_leveling,
|
|||
|
||||
int MachineObject::command_unload_filament()
|
||||
{
|
||||
if (printer_type == "BL-P001"
|
||||
|| printer_type == "BL-P002") {
|
||||
if ((printer_type == "BL-P001" || printer_type == "BL-P002")
|
||||
&& !this->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY)) {
|
||||
// fixed gcode file
|
||||
json j;
|
||||
j["print"]["command"] = "gcode_file";
|
||||
|
|
@ -1859,7 +1901,10 @@ int MachineObject::command_unload_filament()
|
|||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
return this->publish_json(j.dump());
|
||||
}
|
||||
else if (printer_type == "C11") {
|
||||
else if (printer_type == "C11"
|
||||
|| ((printer_type == "BL-P001" || printer_type == "BL-P002")
|
||||
&& this->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY))
|
||||
) {
|
||||
std::string gcode = DeviceManager::load_gcode(printer_type, "ams_unload.gcode");
|
||||
if (gcode.empty()) {
|
||||
return -1;
|
||||
|
|
@ -2245,6 +2290,14 @@ bool MachineObject::is_function_supported(PrinterFunction func)
|
|||
case FUNC_PRINT_ALL:
|
||||
func_name = "FUNC_PRINT_ALL";
|
||||
break;
|
||||
case FUNC_VIRTUAL_TYAY:
|
||||
if (!ams_support_virtual_tray)
|
||||
return false;
|
||||
func_name = "FUNC_VIRTUAL_TYAY";
|
||||
break;
|
||||
case FUNC_FILAMENT_BACKUP:
|
||||
func_name = "FUNC_FILAMENT_BACKUP";
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2345,6 +2398,18 @@ int MachineObject::parse_json(std::string payload)
|
|||
|
||||
if (j.contains("print")) {
|
||||
json jj = j["print"];
|
||||
int sequence_id = 0;
|
||||
if (jj.contains("sequence_id")) {
|
||||
if (jj["sequence_id"].is_string()) {
|
||||
std::string str_seq = jj["sequence_id"].get<std::string>();
|
||||
try {
|
||||
sequence_id = stoi(str_seq);
|
||||
}
|
||||
catch(...) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jj.contains("command")) {
|
||||
if (jj["command"].get<std::string>() == "push_status") {
|
||||
m_push_count++;
|
||||
|
|
@ -2459,6 +2524,11 @@ int MachineObject::parse_json(std::string payload)
|
|||
if (jj.contains("gcode_state")) {
|
||||
this->set_print_state(jj["gcode_state"].get<std::string>());
|
||||
}
|
||||
if (jj.contains("queue_number")) {
|
||||
this->queue_number = jj["queue_number"].get<int>();
|
||||
} else {
|
||||
this->queue_number = 0;
|
||||
}
|
||||
|
||||
if (jj.contains("task_id")) {
|
||||
this->task_id_ = jj["task_id"].get<std::string>();
|
||||
|
|
@ -2619,6 +2689,21 @@ int MachineObject::parse_json(std::string payload)
|
|||
;
|
||||
}
|
||||
|
||||
/*get filam_bak*/
|
||||
try {
|
||||
if (jj.contains("filam_bak")) {
|
||||
filam_bak.clear();
|
||||
if (jj["filam_bak"].is_array()) {
|
||||
for (auto it = jj["filam_bak"].begin(); it != jj["filam_bak"].end(); it++) {
|
||||
filam_bak.push_back(it.value().get<int>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
;
|
||||
}
|
||||
|
||||
/* get fimware type */
|
||||
try {
|
||||
if (jj.contains("lifecycle")) {
|
||||
|
|
@ -3116,6 +3201,16 @@ int MachineObject::parse_json(std::string payload)
|
|||
} else {
|
||||
curr_tray->color = "";
|
||||
}
|
||||
|
||||
curr_tray->cols.clear();
|
||||
if (tray_it->contains("cols")) {
|
||||
if ((*tray_it)["cols"].is_array()) {
|
||||
for (auto it = (*tray_it)["cols"].begin(); it != (*tray_it)["cols"].end(); it++) {
|
||||
curr_tray->cols.push_back(it.value().get<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tray_it->contains("remain")) {
|
||||
curr_tray->remain = (*tray_it)["remain"].get<int>();
|
||||
} else {
|
||||
|
|
@ -3264,6 +3359,16 @@ int MachineObject::parse_json(std::string payload)
|
|||
else {
|
||||
vt_tray.color = "";
|
||||
}
|
||||
|
||||
vt_tray.cols.clear();
|
||||
if (jj["vt_tray"].contains("cols")) {
|
||||
if (jj["vt_tray"].is_array()) {
|
||||
for (auto it = jj["vt_tray"].begin(); it != jj["vt_tray"].end(); it++) {
|
||||
vt_tray.cols.push_back(it.value().get<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jj["vt_tray"].contains("remain")) {
|
||||
vt_tray.remain = jj["vt_tray"]["remain"].get<int>();
|
||||
}
|
||||
|
|
@ -3283,9 +3388,23 @@ int MachineObject::parse_json(std::string payload)
|
|||
} else if (jj["command"].get<std::string>() == "gcode_line") {
|
||||
//ack of gcode_line
|
||||
BOOST_LOG_TRIVIAL(debug) << "parse_json, ack of gcode_line = " << j.dump(4);
|
||||
if (m_agent && is_studio_cmd(sequence_id)) {
|
||||
json t;
|
||||
t["dev_id"] = this->dev_id;
|
||||
t["signal"] = this->wifi_signal;
|
||||
m_agent->track_event("ack_cmd_gcode_line", t.dump());
|
||||
}
|
||||
} else if (jj["command"].get<std::string>() == "project_file") {
|
||||
//ack of project file
|
||||
BOOST_LOG_TRIVIAL(debug) << "parse_json, ack of project_file = " << j.dump(4);
|
||||
|
||||
if (m_agent && is_studio_cmd(sequence_id)) {
|
||||
json t;
|
||||
t["dev_id"] = this->dev_id;
|
||||
t["signal"] = this->wifi_signal;
|
||||
m_agent->track_event("ack_cmd_project_file", t.dump());
|
||||
}
|
||||
|
||||
std::string result;
|
||||
if (jj.contains("result")) {
|
||||
result = jj["result"].get<std::string>();
|
||||
|
|
@ -3324,6 +3443,16 @@ int MachineObject::parse_json(std::string payload)
|
|||
tray_it->second->nozzle_temp_min = std::to_string(jj["nozzle_temp_min"].get<int>());
|
||||
tray_it->second->type = jj["tray_type"].get<std::string>();
|
||||
tray_it->second->color = jj["tray_color"].get<std::string>();
|
||||
|
||||
/*tray_it->second->cols.clear();
|
||||
if (jj.contains("cols")) {
|
||||
if (jj["cols"].is_array()) {
|
||||
for (auto it = jj["cols"].begin(); it != jj["cols"].end(); it++) {
|
||||
tray_it->second->cols.push_back(it.value().get<std::string>());
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
tray_it->second->setting_id = jj["tray_info_idx"].get<std::string>();
|
||||
// delay update
|
||||
tray_it->second->set_hold_count();
|
||||
|
|
@ -3451,6 +3580,7 @@ int MachineObject::parse_json(std::string payload)
|
|||
module_vers.emplace(ver_info.name, ver_info);
|
||||
}
|
||||
parse_version_func();
|
||||
|
||||
bool get_version_result = true;
|
||||
if (j["info"].contains("result"))
|
||||
if (j["info"]["result"].get<std::string>() == "fail")
|
||||
|
|
@ -3542,8 +3672,13 @@ int MachineObject::publish_gcode(std::string gcode_str)
|
|||
j["print"]["param"] = gcode_str;
|
||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
|
||||
if (m_agent)
|
||||
if (m_agent) {
|
||||
j["print"]["user_id"] = m_agent->get_user_id();
|
||||
json t;
|
||||
t["dev_id"] = this->dev_id;
|
||||
t["signal"] = this->wifi_signal;
|
||||
m_agent->track_event("cmd_gcode_line", t.dump());
|
||||
}
|
||||
return publish_json(j.dump());
|
||||
}
|
||||
|
||||
|
|
@ -3765,14 +3900,19 @@ void DeviceManager::on_machine_alive(std::string json_str)
|
|||
std::string printer_signal = j["dev_signal"].get<std::string>();
|
||||
std::string connect_type = j["connect_type"].get<std::string>();
|
||||
std::string bind_state = j["bind_state"].get<std::string>();
|
||||
std::string sec_link = "";
|
||||
if (j.contains("sec_link")) {
|
||||
sec_link = j["sec_link"].get<std::string>();
|
||||
}
|
||||
|
||||
MachineObject* obj;
|
||||
|
||||
/* update userMachineList info */
|
||||
auto it = userMachineList.find(dev_id);
|
||||
if (it != userMachineList.end()) {
|
||||
it->second->dev_ip = dev_ip;
|
||||
it->second->bind_state = bind_state;
|
||||
it->second->dev_ip = dev_ip;
|
||||
it->second->bind_state = bind_state;
|
||||
it->second->bind_sec_link = sec_link;
|
||||
}
|
||||
|
||||
/* update localMachineList */
|
||||
|
|
@ -3786,9 +3926,10 @@ void DeviceManager::on_machine_alive(std::string json_str)
|
|||
obj->dev_ip = dev_ip;
|
||||
/* ip changed reconnect mqtt */
|
||||
}
|
||||
obj->wifi_signal = printer_signal;
|
||||
obj->dev_connection_type = connect_type;
|
||||
obj->bind_state = bind_state;
|
||||
obj->wifi_signal = printer_signal;
|
||||
obj->dev_connection_type= connect_type;
|
||||
obj->bind_state = bind_state;
|
||||
obj->bind_sec_link = sec_link;
|
||||
obj->printer_type = MachineObject::parse_printer_type(printer_type_str);
|
||||
|
||||
// U0 firmware
|
||||
|
|
@ -3811,6 +3952,7 @@ void DeviceManager::on_machine_alive(std::string json_str)
|
|||
obj->wifi_signal = printer_signal;
|
||||
obj->dev_connection_type = connect_type;
|
||||
obj->bind_state = bind_state;
|
||||
obj->bind_sec_link = sec_link;
|
||||
|
||||
//load access code
|
||||
AppConfig* config = Slic3r::GUI::wxGetApp().app_config;
|
||||
|
|
@ -3956,7 +4098,7 @@ void DeviceManager::clean_user_info()
|
|||
userMachineList.clear();
|
||||
}
|
||||
|
||||
bool DeviceManager::set_selected_machine(std::string dev_id)
|
||||
bool DeviceManager::set_selected_machine(std::string dev_id, bool need_disconnect)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "set_selected_machine=" << dev_id;
|
||||
auto my_machine_list = get_my_machine_list();
|
||||
|
|
@ -3966,9 +4108,10 @@ bool DeviceManager::set_selected_machine(std::string dev_id)
|
|||
auto last_selected = my_machine_list.find(selected_machine);
|
||||
if (last_selected != my_machine_list.end()) {
|
||||
if (last_selected->second->connection_type() == "lan") {
|
||||
if (last_selected->second->is_connecting())
|
||||
if (last_selected->second->is_connecting() && !need_disconnect)
|
||||
return false;
|
||||
m_agent->disconnect_printer();
|
||||
|
||||
if (!need_disconnect) {m_agent->disconnect_printer();}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3982,7 +4125,7 @@ bool DeviceManager::set_selected_machine(std::string dev_id)
|
|||
} else {
|
||||
// lan mode printer reconnect printer
|
||||
if (m_agent) {
|
||||
m_agent->disconnect_printer();
|
||||
if (!need_disconnect) {m_agent->disconnect_printer();}
|
||||
it->second->reset();
|
||||
it->second->connect();
|
||||
it->second->set_lan_mode_connection_state(true);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#define GET_VERSION_RETRYS 10
|
||||
#define RETRY_INTERNAL 2000
|
||||
#define VIRTUAL_TRAY_ID 254
|
||||
#define START_SEQ_ID 20000
|
||||
#define END_SEQ_ID 30000
|
||||
|
||||
inline int correct_filament_temperature(int filament_temp)
|
||||
{
|
||||
|
|
@ -89,7 +91,9 @@ enum PrinterFunction {
|
|||
FUNC_AUTO_SWITCH_FILAMENT,
|
||||
FUNC_CHAMBER_FAN,
|
||||
FUNC_EXTRUSION_CALI,
|
||||
FUNC_VIRTUAL_TYAY,
|
||||
FUNC_PRINT_ALL,
|
||||
FUNC_FILAMENT_BACKUP,
|
||||
FUNC_MAX
|
||||
};
|
||||
|
||||
|
|
@ -191,6 +195,7 @@ public:
|
|||
std::string type;
|
||||
std::string sub_brands;
|
||||
std::string color;
|
||||
std::vector<std::string> cols;
|
||||
std::string weight;
|
||||
std::string diameter;
|
||||
std::string temp;
|
||||
|
|
@ -389,7 +394,7 @@ public:
|
|||
};
|
||||
|
||||
/* static members and functions */
|
||||
static inline int m_sequence_id = 20000;
|
||||
static inline int m_sequence_id = START_SEQ_ID;
|
||||
static std::string parse_printer_type(std::string type_str);
|
||||
static std::string get_preset_printer_model_name(std::string printer_type);
|
||||
static std::string get_preset_printer_thumbnail_img(std::string printer_type);
|
||||
|
|
@ -430,9 +435,12 @@ public:
|
|||
std::string get_printer_thumbnail_img_str();
|
||||
std::string product_name; // set by iot service, get /user/print
|
||||
|
||||
std::vector<int> filam_bak;
|
||||
|
||||
std::string bind_user_name;
|
||||
std::string bind_user_id;
|
||||
std::string bind_state; /* free | occupied */
|
||||
std::string bind_sec_link;
|
||||
bool is_avaliable() { return bind_state == "free"; }
|
||||
time_t last_alive;
|
||||
bool m_is_online;
|
||||
|
|
@ -605,7 +613,8 @@ public:
|
|||
void parse_status(int flag);
|
||||
|
||||
/* printing status */
|
||||
std::string print_status; /* enum string: FINISH, RUNNING, PAUSE, INIT, FAILED */
|
||||
std::string print_status; /* enum string: FINISH, SLICING, RUNNING, PAUSE, INIT, FAILED */
|
||||
int queue_number = 0;
|
||||
std::string iot_print_status; /* iot */
|
||||
PrintingSpeedLevel printing_speed_lvl;
|
||||
int printing_speed_mag = 100;
|
||||
|
|
@ -682,10 +691,12 @@ public:
|
|||
~MachineObject();
|
||||
|
||||
void parse_version_func();
|
||||
bool is_studio_cmd(int seq);
|
||||
/* command commands */
|
||||
int command_get_version(bool with_retry = true);
|
||||
int command_request_push_all();
|
||||
int command_pushing(std::string cmd);
|
||||
int command_clean_print_error(std::string task_id, int print_error);
|
||||
|
||||
/* command upgrade */
|
||||
int command_upgrade_confirm();
|
||||
|
|
@ -816,7 +827,7 @@ public:
|
|||
void erase_user_machine(std::string dev_id);
|
||||
void clean_user_info();
|
||||
|
||||
bool set_selected_machine(std::string dev_id);
|
||||
bool set_selected_machine(std::string dev_id, bool need_disconnect = false);
|
||||
MachineObject* get_selected_machine();
|
||||
|
||||
/* return machine has access code and user machine if login*/
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ wxWindow* BitmapTextRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelRec
|
|||
position, labelRect.GetSize(), wxTE_PROCESS_ENTER);
|
||||
text_editor->SetInsertionPointEnd();
|
||||
text_editor->SelectAll();
|
||||
text_editor->SetBackgroundColour(parent->GetBackgroundColour());
|
||||
|
||||
return text_editor;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,7 +178,9 @@ void GCodeViewer::InstanceVBuffer::Ranges::reset()
|
|||
void GCodeViewer::InstanceVBuffer::reset()
|
||||
{
|
||||
s_ids.clear();
|
||||
s_ids.shrink_to_fit();
|
||||
buffer.clear();
|
||||
buffer.shrink_to_fit();
|
||||
render_ranges.reset();
|
||||
}
|
||||
|
||||
|
|
@ -510,14 +512,14 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he
|
|||
imgui.pop_toolbar_style();
|
||||
}
|
||||
|
||||
void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& filename, std::vector<size_t> &&lines_ends)
|
||||
void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& filename, const std::vector<size_t> &lines_ends)
|
||||
{
|
||||
assert(! m_file.is_open());
|
||||
if (m_file.is_open())
|
||||
return;
|
||||
|
||||
m_filename = filename;
|
||||
m_lines_ends = std::move(lines_ends);
|
||||
m_lines_ends = lines_ends;
|
||||
|
||||
m_selected_line_id = 0;
|
||||
m_last_lines_size = 0;
|
||||
|
|
@ -627,7 +629,7 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, f
|
|||
imgui.set_next_window_pos(right, top, ImGuiCond_Always, 1.0f, 0.0f);
|
||||
imgui.set_next_window_size(0.0f, wnd_height, ImGuiCond_Always);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::SetNextWindowBgAlpha(0.6f);
|
||||
ImGui::SetNextWindowBgAlpha(0.8f);
|
||||
imgui.begin(std::string("G-code"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
||||
|
||||
// center the text in the window by pushing down the first line
|
||||
|
|
@ -909,6 +911,7 @@ void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle)
|
|||
void GCodeViewer::on_change_color_mode(bool is_dark) {
|
||||
m_is_dark = is_dark;
|
||||
m_sequential_view.marker.on_change_color_mode(m_is_dark);
|
||||
m_sequential_view.gcode_window.on_change_color_mode(m_is_dark);
|
||||
}
|
||||
|
||||
void GCodeViewer::set_scale(float scale)
|
||||
|
|
@ -1098,9 +1101,20 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr
|
|||
}
|
||||
|
||||
m_fold = false;
|
||||
|
||||
bool only_gcode_3mf = false;
|
||||
PartPlate* current_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
|
||||
bool current_has_print_instances = current_plate->has_printable_instances();
|
||||
if (current_plate->is_slice_result_valid() && wxGetApp().model().objects.empty() && !current_has_print_instances)
|
||||
only_gcode_3mf = true;
|
||||
m_layers_slider->set_menu_enable(!(only_gcode || only_gcode_3mf));
|
||||
m_layers_slider->set_as_dirty();
|
||||
m_moves_slider->set_as_dirty();
|
||||
|
||||
//BBS
|
||||
m_conflict_result = gcode_result.conflict_result;
|
||||
if (m_conflict_result) { m_conflict_result.value().layer = m_layers.get_l_at(m_conflict_result.value()._height); }
|
||||
|
||||
//BBS: add mutex for protection of gcode result
|
||||
gcode_result.unlock();
|
||||
//BBS: add logs
|
||||
|
|
@ -1230,6 +1244,7 @@ void GCodeViewer::reset()
|
|||
|
||||
m_moves_count = 0;
|
||||
m_ssid_to_moveid_map.clear();
|
||||
m_ssid_to_moveid_map.shrink_to_fit();
|
||||
for (TBuffer& buffer : m_buffers) {
|
||||
buffer.reset();
|
||||
}
|
||||
|
|
@ -1800,7 +1815,10 @@ void GCodeViewer::update_layers_slider_mode()
|
|||
void GCodeViewer::update_marker_curr_move() {
|
||||
if ((int)m_last_result_id != -1) {
|
||||
auto it = std::find_if(m_gcode_result->moves.begin(), m_gcode_result->moves.end(), [this](auto move) {
|
||||
return move.gcode_id == static_cast<uint64_t>(m_sequential_view.gcode_ids[m_sequential_view.current.last]);
|
||||
if (m_sequential_view.current.last < m_sequential_view.gcode_ids.size() && m_sequential_view.current.last >= 0) {
|
||||
return move.gcode_id == static_cast<uint64_t>(m_sequential_view.gcode_ids[m_sequential_view.current.last]);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (it != m_gcode_result->moves.end())
|
||||
m_sequential_view.marker.update_curr_move(*it);
|
||||
|
|
@ -3183,19 +3201,8 @@ void GCodeViewer::load_shells(const Print& print, bool initialized, bool force_p
|
|||
}
|
||||
|
||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF) {
|
||||
// BBS
|
||||
// adds wipe tower's volume
|
||||
std::vector<int> print_extruders;
|
||||
for (auto print_obj : print.objects()) {
|
||||
ModelObject* mo = print_obj->model_object();
|
||||
for (ModelVolume* mv : mo->volumes) {
|
||||
std::vector<int> volume_extruders = mv->get_extruders();
|
||||
print_extruders.insert(print_extruders.end(), volume_extruders.begin(), volume_extruders.end());
|
||||
}
|
||||
}
|
||||
std::sort(print_extruders.begin(), print_extruders.end());
|
||||
auto it_end = std::unique(print_extruders.begin(), print_extruders.end());
|
||||
print_extruders.resize(std::distance(print_extruders.begin(), it_end));
|
||||
// BBS: adds wipe tower's volume
|
||||
std::vector<unsigned int> print_extruders = print.extruders(true);
|
||||
int extruders_count = print_extruders.size();
|
||||
|
||||
const double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2);
|
||||
|
|
@ -4363,7 +4370,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
|||
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, ImVec4(0.42f, 0.42f, 0.42f, 1.00f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
|
||||
ImGui::SetNextWindowBgAlpha(0.6f);
|
||||
ImGui::SetNextWindowBgAlpha(0.8f);
|
||||
const float max_height = 0.75f * static_cast<float>(cnv_size.get_height());
|
||||
const float child_height = 0.3333f * max_height;
|
||||
ImGui::SetNextWindowSizeConstraints({ 0.0f, 0.0f }, { -1.0f, max_height });
|
||||
|
|
|
|||
|
|
@ -492,6 +492,11 @@ class GCodeViewer
|
|||
std::vector<Endpoints>& get_endpoints() { return m_endpoints; }
|
||||
double get_z_at(unsigned int id) const { return (id < m_zs.size()) ? m_zs[id] : 0.0; }
|
||||
Endpoints get_endpoints_at(unsigned int id) const { return (id < m_endpoints.size()) ? m_endpoints[id] : Endpoints(); }
|
||||
int get_l_at(double z) const
|
||||
{
|
||||
auto iter = std::upper_bound(m_zs.begin(), m_zs.end(), z);
|
||||
return std::distance(m_zs.begin(), iter);
|
||||
}
|
||||
|
||||
bool operator != (const Layers& other) const {
|
||||
if (m_zs != other.m_zs)
|
||||
|
|
@ -650,6 +655,7 @@ public:
|
|||
std::string parameters;
|
||||
std::string comment;
|
||||
};
|
||||
bool m_is_dark = false;
|
||||
bool m_visible{ true };
|
||||
uint64_t m_selected_line_id{ 0 };
|
||||
size_t m_last_lines_size{ 0 };
|
||||
|
|
@ -663,12 +669,15 @@ public:
|
|||
public:
|
||||
GCodeWindow() = default;
|
||||
~GCodeWindow() { stop_mapping_file(); }
|
||||
void load_gcode(const std::string& filename, std::vector<size_t> &&lines_ends);
|
||||
void load_gcode(const std::string& filename, const std::vector<size_t> &lines_ends);
|
||||
void reset() {
|
||||
stop_mapping_file();
|
||||
m_lines_ends.clear();
|
||||
m_lines_ends.shrink_to_fit();
|
||||
m_lines.clear();
|
||||
m_lines.shrink_to_fit();
|
||||
m_filename.clear();
|
||||
m_filename.shrink_to_fit();
|
||||
}
|
||||
|
||||
void toggle_visibility() { m_visible = !m_visible; }
|
||||
|
|
@ -676,6 +685,7 @@ public:
|
|||
//BBS: GUI refactor: add canvas size
|
||||
//void render(float top, float bottom, uint64_t curr_line_id) const;
|
||||
void render(float top, float bottom, float right, uint64_t curr_line_id) const;
|
||||
void on_change_color_mode(bool is_dark) { m_is_dark = is_dark; }
|
||||
|
||||
void stop_mapping_file();
|
||||
};
|
||||
|
|
@ -725,6 +735,9 @@ public:
|
|||
Count
|
||||
};
|
||||
|
||||
//BBS
|
||||
ConflictResultOpt m_conflict_result;
|
||||
|
||||
private:
|
||||
std::vector<int> m_plater_extruder;
|
||||
bool m_gl_data_initialized{ false };
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@
|
|||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#endif
|
||||
#include <imgui/imgui_internal.h>
|
||||
|
||||
static constexpr const float TRACKBALLSIZE = 0.8f;
|
||||
|
|
@ -679,6 +682,7 @@ GLCanvas3D::Mouse::Mouse()
|
|||
, position(DBL_MAX, DBL_MAX)
|
||||
, scene_position(DBL_MAX, DBL_MAX, DBL_MAX)
|
||||
, ignore_left_up(false)
|
||||
, ignore_right_up(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -796,8 +800,6 @@ void GLCanvas3D::Labels::render(const std::vector<const ModelInstance*>& sorted_
|
|||
imgui.begin(owner.title, ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
||||
float win_w = ImGui::GetWindowWidth();
|
||||
float label_len = imgui.calc_text_size(owner.label).x;
|
||||
ImGui::SetCursorPosX(0.5f * (win_w - label_len));
|
||||
ImGui::AlignTextToFramePadding();
|
||||
imgui.text(owner.label);
|
||||
|
||||
|
|
@ -1731,6 +1733,44 @@ bool GLCanvas3D::make_current_for_postinit() {
|
|||
return _set_current();
|
||||
}
|
||||
|
||||
Points GLCanvas3D::estimate_wipe_tower_points(int plate_index, bool global) const
|
||||
{
|
||||
PartPlateList & ppl = wxGetApp().plater()->get_partplate_list();
|
||||
DynamicPrintConfig &proj_cfg = wxGetApp().preset_bundle->project_config;
|
||||
auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||
int plate_count = ppl.get_plate_count();
|
||||
float x = dynamic_cast<const ConfigOptionFloats *>(proj_cfg.option("wipe_tower_x"))->get_at(plate_index);
|
||||
float y = dynamic_cast<const ConfigOptionFloats *>(proj_cfg.option("wipe_tower_y"))->get_at(plate_index);
|
||||
if (plate_index >= plate_count) { plate_index = 0; }
|
||||
float w = dynamic_cast<const ConfigOptionFloat *>(m_config->option("prime_tower_width"))->value;
|
||||
float v = dynamic_cast<const ConfigOptionFloat *>(m_config->option("prime_volume"))->value;
|
||||
Vec3d wipe_tower_size = ppl.get_plate(plate_index)->estimate_wipe_tower_size(w, v);
|
||||
|
||||
if (wipe_tower_size(1) == 0) {
|
||||
// when depth is unavailable (no items on this plate), we have to estimate the depth using the extruder number of all plates
|
||||
std::set<int> extruder_ids;
|
||||
if (global) {
|
||||
auto objs = wxGetApp().obj_list()->objects();
|
||||
for (ModelObject *obj : *objs) {
|
||||
for (ModelVolume *volume : obj->volumes) {
|
||||
std::vector<int> es = volume->get_extruders();
|
||||
extruder_ids.insert(es.begin(), es.end());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PartPlate* pl = ppl.get_plate(plate_index);
|
||||
std::vector<int> es = pl->get_extruders();
|
||||
extruder_ids.insert(es.begin(), es.end());
|
||||
}
|
||||
int extruder_size = extruder_ids.size();
|
||||
wipe_tower_size(1) = extruder_size * print.wipe_tower_data(extruder_size).depth + 2 * print.wipe_tower_data().brim_width;
|
||||
}
|
||||
Vec3d plate_origin = ppl.get_plate(plate_index)->get_origin();
|
||||
Point wt_min_corner{scale_(x), scale_(y)};
|
||||
Point wt_max_corner(scale_(x + wipe_tower_size(0)), scale_(y + wipe_tower_size(1)));
|
||||
return {wt_min_corner, {wt_max_corner.x(), wt_min_corner.y()}, wt_max_corner, {wt_min_corner.x(), wt_max_corner.y()}};
|
||||
}
|
||||
|
||||
void GLCanvas3D::render(bool only_init)
|
||||
{
|
||||
if (m_in_render) {
|
||||
|
|
@ -1988,24 +2028,25 @@ void GLCanvas3D::render(bool only_init)
|
|||
m_render_stats.increment_fps_counter();
|
||||
}
|
||||
|
||||
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type)
|
||||
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type, bool use_top_view, bool for_picking)
|
||||
{
|
||||
render_thumbnail(thumbnail_data, w, h, thumbnail_params, m_volumes, camera_type);
|
||||
render_thumbnail(thumbnail_data, w, h, thumbnail_params, m_volumes, camera_type, use_top_view, for_picking);
|
||||
}
|
||||
|
||||
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type)
|
||||
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
|
||||
const GLVolumeCollection& volumes, Camera::EType camera_type, bool use_top_view, bool for_picking)
|
||||
{
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("thumbnail");
|
||||
ModelObjectPtrs& model_objects = GUI::wxGetApp().model().objects;
|
||||
std::vector<std::array<float, 4>> colors = ::get_extruders_colors();
|
||||
switch (OpenGLManager::get_framebuffers_type())
|
||||
{
|
||||
case OpenGLManager::EFramebufferType::Arb:
|
||||
{ render_thumbnail_framebuffer(thumbnail_data, w, h, thumbnail_params,
|
||||
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type); break; }
|
||||
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type, use_top_view, for_picking); break; }
|
||||
case OpenGLManager::EFramebufferType::Ext:
|
||||
{ render_thumbnail_framebuffer_ext(thumbnail_data, w, h, thumbnail_params,
|
||||
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type); break; }
|
||||
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type, use_top_view, for_picking); break; }
|
||||
default:
|
||||
{ render_thumbnail_legacy(thumbnail_data, w, h, thumbnail_params,
|
||||
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type); break; }
|
||||
|
|
@ -2572,8 +2613,12 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
if (wt && (timelapse_enabled || filaments_count > 1)) {
|
||||
for (int plate_id = 0; plate_id < n_plates; plate_id++) {
|
||||
// If print ByObject and there is only one object in the plate, the wipe tower is allowed to be generated.
|
||||
if (co != nullptr && co->value == PrintSequence::ByObject && ppl.get_plate(plate_id)->printable_instance_size() != 1)
|
||||
continue;
|
||||
PartPlate* part_plate = ppl.get_plate(plate_id);
|
||||
if (part_plate->get_print_seq() == PrintSequence::ByObject ||
|
||||
(part_plate->get_print_seq() == PrintSequence::ByDefault && co != nullptr && co->value == PrintSequence::ByObject)) {
|
||||
if (ppl.get_plate(plate_id)->printable_instance_size() != 1)
|
||||
continue;
|
||||
}
|
||||
|
||||
DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
|
||||
float x = dynamic_cast<const ConfigOptionFloats*>(proj_cfg.option("wipe_tower_x"))->get_at(plate_id);
|
||||
|
|
@ -2714,6 +2759,7 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co
|
|||
//BBS: always load shell at preview, do this in load_shells
|
||||
//m_gcode_viewer.update_shells_color_by_extruder(m_config);
|
||||
_set_warning_notification_if_needed(EWarning::ToolpathOutside);
|
||||
_set_warning_notification_if_needed(EWarning::GCodeConflict);
|
||||
}
|
||||
|
||||
m_gcode_viewer.refresh(gcode_result, str_tool_colors);
|
||||
|
|
@ -2790,6 +2836,11 @@ void GLCanvas3D::bind_event_handlers()
|
|||
m_canvas->Bind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this);
|
||||
m_canvas->Bind(wxEVT_PAINT, &GLCanvas3D::on_paint, this);
|
||||
m_canvas->Bind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this);
|
||||
m_canvas->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& evt) {
|
||||
ImGui::SetWindowFocus(nullptr);
|
||||
render();
|
||||
evt.Skip();
|
||||
});
|
||||
m_event_handlers_bound = true;
|
||||
|
||||
m_canvas->Bind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this);
|
||||
|
|
@ -3349,27 +3400,27 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
|||
else if (m_gizmos.is_enabled() && !m_selection.is_empty() && m_canvas_type != CanvasAssembleView) {
|
||||
translationProcessor.process(evt);
|
||||
|
||||
//switch (keyCode)
|
||||
//{
|
||||
//case WXK_NUMPAD_PAGEUP: case WXK_PAGEUP:
|
||||
//case WXK_NUMPAD_PAGEDOWN: case WXK_PAGEDOWN:
|
||||
//{
|
||||
// do_rotate(L("Tool Rotate"));
|
||||
// m_gizmos.update_data();
|
||||
switch (keyCode)
|
||||
{
|
||||
case WXK_NUMPAD_PAGEUP: case WXK_PAGEUP:
|
||||
case WXK_NUMPAD_PAGEDOWN: case WXK_PAGEDOWN:
|
||||
{
|
||||
do_rotate(L("Tool Rotate"));
|
||||
m_gizmos.update_data();
|
||||
|
||||
// // BBS
|
||||
// //wxGetApp().obj_manipul()->set_dirty();
|
||||
// // Let the plater know that the dragging finished, so a delayed refresh
|
||||
// // of the scene with the background processing data should be performed.
|
||||
// post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
|
||||
// // updates camera target constraints
|
||||
// refresh_camera_scene_box();
|
||||
// m_dirty = true;
|
||||
// BBS
|
||||
//wxGetApp().obj_manipul()->set_dirty();
|
||||
// Let the plater know that the dragging finished, so a delayed refresh
|
||||
// of the scene with the background processing data should be performed.
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
|
||||
// updates camera target constraints
|
||||
refresh_camera_scene_box();
|
||||
m_dirty = true;
|
||||
|
||||
// break;
|
||||
//}
|
||||
//default: { break; }
|
||||
//}
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
|
||||
// BBS: add select view logic
|
||||
|
|
@ -3427,22 +3478,22 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
|||
else if (keyCode == WXK_CONTROL)
|
||||
m_dirty = true;
|
||||
else if (m_gizmos.is_enabled() && !m_selection.is_empty() && m_canvas_type != CanvasAssembleView) {
|
||||
// auto do_rotate = [this](double angle_z_rad) {
|
||||
// m_selection.start_dragging();
|
||||
// m_selection.rotate(Vec3d(0.0, 0.0, angle_z_rad), TransformationType(TransformationType::World_Relative_Joint));
|
||||
// m_selection.stop_dragging();
|
||||
// m_dirty = true;
|
||||
//// wxGetApp().obj_manipul()->set_dirty();
|
||||
// };
|
||||
auto _do_rotate = [this](double angle_z_rad) {
|
||||
m_selection.start_dragging();
|
||||
m_selection.rotate(Vec3d(0.0, 0.0, angle_z_rad), TransformationType(TransformationType::World_Relative_Joint));
|
||||
m_selection.stop_dragging();
|
||||
m_dirty = true;
|
||||
// wxGetApp().obj_manipul()->set_dirty();
|
||||
};
|
||||
|
||||
translationProcessor.process(evt);
|
||||
|
||||
//switch (keyCode)
|
||||
//{
|
||||
//case WXK_NUMPAD_PAGEUP: case WXK_PAGEUP: { do_rotate(0.25 * M_PI); break; }
|
||||
//case WXK_NUMPAD_PAGEDOWN: case WXK_PAGEDOWN: { do_rotate(-0.25 * M_PI); break; }
|
||||
//default: { break; }
|
||||
//}
|
||||
switch (keyCode)
|
||||
{
|
||||
case WXK_NUMPAD_PAGEUP: case WXK_PAGEUP: { _do_rotate(0.25 * M_PI); break; }
|
||||
case WXK_NUMPAD_PAGEDOWN: case WXK_PAGEDOWN: { _do_rotate(-0.25 * M_PI); break; }
|
||||
default: { break; }
|
||||
}
|
||||
} else if (!m_gizmos.is_enabled()) {
|
||||
// DoubleSlider navigation in Preview
|
||||
if (m_canvas_type == CanvasPreview) {
|
||||
|
|
@ -3598,7 +3649,22 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
|
|||
#else
|
||||
double direction_factor = 1.0;
|
||||
#endif
|
||||
_update_camera_zoom(direction_factor * (double)evt.GetWheelRotation() / (double)evt.GetWheelDelta());
|
||||
auto delta = direction_factor * (double)evt.GetWheelRotation() / (double)evt.GetWheelDelta();
|
||||
bool zoom_to_mouse = wxGetApp().app_config->get("zoom_to_mouse") == "true";
|
||||
if (!zoom_to_mouse) {// zoom to center
|
||||
_update_camera_zoom(delta);
|
||||
}
|
||||
else {
|
||||
auto cnv_size = get_canvas_size();
|
||||
auto screen_center_3d_pos = _mouse_to_3d({ cnv_size.get_width() * 0.5, cnv_size.get_height() * 0.5 });
|
||||
auto mouse_3d_pos = _mouse_to_3d({evt.GetX(), evt.GetY()});
|
||||
Vec3d displacement = mouse_3d_pos - screen_center_3d_pos;
|
||||
wxGetApp().plater()->get_camera().translate(displacement);
|
||||
auto origin_zoom = wxGetApp().plater()->get_camera().get_zoom();
|
||||
_update_camera_zoom(delta);
|
||||
auto new_zoom = wxGetApp().plater()->get_camera().get_zoom();
|
||||
wxGetApp().plater()->get_camera().translate((-displacement) / (new_zoom / origin_zoom));
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::on_timer(wxTimerEvent& evt)
|
||||
|
|
@ -3747,6 +3813,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
m_mouse.ignore_left_up = true;
|
||||
m_tooltip.set_in_imgui(false);
|
||||
if (imgui->update_mouse_data(evt)) {
|
||||
if (evt.LeftDown() && m_canvas != nullptr)
|
||||
m_canvas->SetFocus();
|
||||
m_mouse.position = evt.Leaving() ? Vec2d(-1.0, -1.0) : pos.cast<double>();
|
||||
m_tooltip.set_in_imgui(true);
|
||||
render();
|
||||
|
|
@ -3874,6 +3942,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
default: { break; }
|
||||
}
|
||||
}
|
||||
else if (evt.LeftUp() &&
|
||||
m_gizmos.get_current_type() == GLGizmosManager::EType::Scale &&
|
||||
m_gizmos.get_current()->get_state() == GLGizmoBase::EState::On) {
|
||||
wxGetApp().obj_list()->selection_changed();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -3904,7 +3977,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
p = p->GetParent();
|
||||
auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
|
||||
if (top_level_wnd && top_level_wnd->IsActive() && !wxGetApp().get_side_menu_popup_status())
|
||||
m_canvas->SetFocus();
|
||||
;// m_canvas->SetFocus();
|
||||
m_mouse.position = pos.cast<double>();
|
||||
m_tooltip_enabled = false;
|
||||
// 1) forces a frame render to ensure that m_hover_volume_idxs is updated even when the user right clicks while
|
||||
|
|
@ -4162,6 +4235,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
|
||||
camera.set_target(camera.get_target() + orig - cur_pos);
|
||||
m_dirty = true;
|
||||
m_mouse.ignore_right_up = true;
|
||||
}
|
||||
|
||||
m_mouse.drag.start_position_2D = pos;
|
||||
|
|
@ -4251,7 +4325,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
logical_pos = logical_pos.cwiseQuotient(Vec2d(factor, factor));
|
||||
#endif // ENABLE_RETINA_GL
|
||||
|
||||
if (!m_mouse.dragging) {
|
||||
if (!m_mouse.ignore_right_up) {
|
||||
//BBS post right click event
|
||||
if (!m_hover_plate_idxs.empty()) {
|
||||
post_event(RBtnPlateEvent(EVT_GLCANVAS_PLATE_RIGHT_CLICK, { logical_pos, m_hover_plate_idxs.front() }));
|
||||
|
|
@ -4412,9 +4486,7 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
|||
ModelObject* m = m_model->objects[i.first];
|
||||
const double shift_z = m->get_instance_min_z(i.second);
|
||||
//BBS: don't call translate if the z is zero
|
||||
//BBS: removing sinking logic
|
||||
if (shift_z != 0.0f) {
|
||||
//if ((current_printer_technology() == ptSLA || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
|
||||
if ((current_printer_technology() == ptSLA || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
|
||||
const Vec3d shift(0.0, 0.0, -shift_z);
|
||||
m_selection.translate(i.first, i.second, shift);
|
||||
m->translate_instance(i.second, shift);
|
||||
|
|
@ -4460,9 +4532,8 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
|||
if (!snapshot_type.empty())
|
||||
wxGetApp().plater()->take_snapshot(snapshot_type);
|
||||
|
||||
//BBS: removing sinking logic
|
||||
// stores current min_z of instances
|
||||
/*std::map<std::pair<int, int>, double> min_zs;
|
||||
std::map<std::pair<int, int>, double> min_zs;
|
||||
for (int i = 0; i < static_cast<int>(m_model->objects.size()); ++i) {
|
||||
const ModelObject* obj = m_model->objects[i];
|
||||
for (int j = 0; j < static_cast<int>(obj->instances.size()); ++j) {
|
||||
|
|
@ -4475,7 +4546,7 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
|||
min_zs[{ i, j }] = obj->instance_bounding_box(j).min.z();
|
||||
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||
|
||||
|
|
@ -4520,9 +4591,7 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
|||
//BBS: don't call translate if the z is zero
|
||||
const double shift_z = m->get_instance_min_z(i.second);
|
||||
// leave sinking instances as sinking
|
||||
//BBS: removing sinking logic
|
||||
if (shift_z != 0.0f) {
|
||||
//if ((min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD)&&(shift_z != 0.0f)) {
|
||||
if ((min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD)&&(shift_z != 0.0f)) {
|
||||
const Vec3d shift(0.0, 0.0, -shift_z);
|
||||
m_selection.translate(i.first, i.second, shift);
|
||||
m->translate_instance(i.second, shift);
|
||||
|
|
@ -4549,9 +4618,8 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
|||
if (!snapshot_type.empty())
|
||||
wxGetApp().plater()->take_snapshot(snapshot_type);
|
||||
|
||||
//BBS: removing sinking logic
|
||||
// stores current min_z of instances
|
||||
/*std::map<std::pair<int, int>, double> min_zs;
|
||||
std::map<std::pair<int, int>, double> min_zs;
|
||||
if (!snapshot_type.empty()) {
|
||||
for (int i = 0; i < static_cast<int>(m_model->objects.size()); ++i) {
|
||||
const ModelObject* obj = m_model->objects[i];
|
||||
|
|
@ -4559,7 +4627,7 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
|||
min_zs[{ i, j }] = obj->instance_bounding_box(j).min.z();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||
|
||||
|
|
@ -4605,9 +4673,7 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
|||
//BBS: don't call translate if the z is zero
|
||||
double shift_z = m->get_instance_min_z(i.second);
|
||||
// leave sinking instances as sinking
|
||||
//BBS: removing sinking logic
|
||||
if (shift_z != 0.0f) {
|
||||
//if ((min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
|
||||
if ((min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
|
||||
Vec3d shift(0.0, 0.0, -shift_z);
|
||||
m_selection.translate(i.first, i.second, shift);
|
||||
m->translate_instance(i.second, shift);
|
||||
|
|
@ -4652,9 +4718,8 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
|
|||
if (!snapshot_type.empty())
|
||||
wxGetApp().plater()->take_snapshot(snapshot_type);
|
||||
|
||||
//BBS: removing sinking logic
|
||||
// stores current min_z of instances
|
||||
/*std::map<std::pair<int, int>, double> min_zs;
|
||||
std::map<std::pair<int, int>, double> min_zs;
|
||||
if (!snapshot_type.empty()) {
|
||||
for (int i = 0; i < static_cast<int>(m_model->objects.size()); ++i) {
|
||||
const ModelObject* obj = m_model->objects[i];
|
||||
|
|
@ -4662,7 +4727,7 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
|
|||
min_zs[{ i, j }] = obj->instance_bounding_box(j).min.z();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||
|
||||
|
|
@ -4705,9 +4770,7 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
|
|||
//BBS: don't call translate if the z is zero
|
||||
double shift_z = m->get_instance_min_z(i.second);
|
||||
// leave sinking instances as sinking
|
||||
//BBS: removing sinking logic
|
||||
if (shift_z != 0.0f) {
|
||||
//if ((min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD)&&(shift_z != 0.0f)) {
|
||||
if ((min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD)&&(shift_z != 0.0f)) {
|
||||
Vec3d shift(0.0, 0.0, -shift_z);
|
||||
m_selection.translate(i.first, i.second, shift);
|
||||
m->translate_instance(i.second, shift);
|
||||
|
|
@ -4752,6 +4815,7 @@ void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool foc
|
|||
void GLCanvas3D::handle_layers_data_focus_event(const t_layer_height_range range, const EditorType type)
|
||||
{
|
||||
std::string field = "layer_" + std::to_string(type) + "_" + std::to_string(range.first) + "_" + std::to_string(range.second);
|
||||
m_gizmos.reset_all_states();
|
||||
handle_sidebar_focus_event(field, true);
|
||||
}
|
||||
|
||||
|
|
@ -4926,6 +4990,7 @@ void GLCanvas3D::mouse_up_cleanup()
|
|||
m_mouse.set_start_position_2D_as_invalid();
|
||||
m_mouse.dragging = false;
|
||||
m_mouse.ignore_left_up = false;
|
||||
m_mouse.ignore_right_up = false;
|
||||
m_dirty = true;
|
||||
|
||||
if (m_canvas->HasCapture())
|
||||
|
|
@ -4977,12 +5042,14 @@ void GLCanvas3D::update_sequential_clearance()
|
|||
for (size_t i = 0; i < m_model->objects.size(); ++i) {
|
||||
ModelObject* model_object = m_model->objects[i];
|
||||
ModelInstance* model_instance0 = model_object->instances.front();
|
||||
Polygon hull_2d = offset(model_object->convex_hull_2d(Geometry::assemble_transform({ 0.0, 0.0, model_instance0->get_offset().z() }, model_instance0->get_rotation(),
|
||||
model_instance0->get_scaling_factor(), model_instance0->get_mirror())),
|
||||
Polygon hull_no_offset = model_object->convex_hull_2d(Geometry::assemble_transform({ 0.0, 0.0, model_instance0->get_offset().z() }, model_instance0->get_rotation(),
|
||||
model_instance0->get_scaling_factor(), model_instance0->get_mirror()));
|
||||
auto tmp = offset(hull_no_offset,
|
||||
// Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
|
||||
// exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
|
||||
shrink_factor,
|
||||
jtRound, mitter_limit).front();
|
||||
jtRound, mitter_limit);
|
||||
Polygon hull_2d = !tmp.empty() ? tmp.front() : hull_no_offset;// tmp may be empty due to clipper's bug, see STUDIO-2452
|
||||
|
||||
Pointf3s& cache_hull_2d = m_sequential_print_clearance.m_hull_2d_cache.emplace_back(Pointf3s());
|
||||
cache_hull_2d.reserve(hull_2d.points.size());
|
||||
|
|
@ -5393,7 +5460,9 @@ static void debug_output_thumbnail(const ThumbnailData& thumbnail_data)
|
|||
}
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||
|
||||
void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type)
|
||||
void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params,
|
||||
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
|
||||
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view, bool for_picking)
|
||||
{
|
||||
//BBS modify visible calc function
|
||||
int plate_idx = thumbnail_params.plate_id;
|
||||
|
|
@ -5414,7 +5483,14 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||
auto is_visible = [plate_idx, plate_build_volume](const GLVolume& v) {
|
||||
bool ret = v.printable;
|
||||
if (plate_idx >= 0) {
|
||||
ret &= plate_build_volume.contains(v.transformed_convex_hull_bounding_box());
|
||||
bool contained = false;
|
||||
BoundingBoxf3 plate_bbox = plate_build_volume;
|
||||
plate_bbox.min(2) = -1e10;
|
||||
const BoundingBoxf3& volume_bbox = v.transformed_convex_hull_bounding_box();
|
||||
if (plate_bbox.contains(volume_bbox) && (volume_bbox.max(2) > 0)) {
|
||||
contained = true;
|
||||
}
|
||||
ret &= contained;
|
||||
}
|
||||
else {
|
||||
ret &= (!v.shader_outside_printer_detection_enabled || !v.is_outside);
|
||||
|
|
@ -5436,7 +5512,7 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: plate_idx %1% volumes size %2%, shader %3%") % plate_idx % visible_volumes.size() %shader;
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: plate_idx %1% volumes size %2%, shader %3%, use_top_view=%4%, for_picking=%5%") % plate_idx % visible_volumes.size() %shader %use_top_view %for_picking;
|
||||
//BoundingBoxf3 volumes_box = plate_build_volume;
|
||||
BoundingBoxf3 volumes_box;
|
||||
volumes_box.min.z() = 0;
|
||||
|
|
@ -5446,15 +5522,16 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||
volumes_box.merge(vol->transformed_bounding_box());
|
||||
}
|
||||
}
|
||||
volumes_box.min.z() = -Slic3r::BuildVolume::SceneEpsilon;
|
||||
double width = volumes_box.max.x() - volumes_box.min.x();
|
||||
double depth = volumes_box.max.y() - volumes_box.min.y();
|
||||
double height = volumes_box.max.z() - volumes_box.min.z();
|
||||
volumes_box.max.x() = volumes_box.max.x() + width * 0.05f;
|
||||
volumes_box.min.x() = volumes_box.min.x() - width * 0.05f;
|
||||
volumes_box.max.y() = volumes_box.max.y() + depth * 0.05f;
|
||||
volumes_box.min.y() = volumes_box.min.y() - depth * 0.05f;
|
||||
volumes_box.max.z() = volumes_box.max.z() + height * 0.05f;
|
||||
volumes_box.min.z() = volumes_box.min.z() - height * 0.05f;
|
||||
volumes_box.max.x() = volumes_box.max.x() + width * 0.1f;
|
||||
volumes_box.min.x() = volumes_box.min.x() - width * 0.1f;
|
||||
volumes_box.max.y() = volumes_box.max.y() + depth * 0.1f;
|
||||
volumes_box.min.y() = volumes_box.min.y() - depth * 0.1f;
|
||||
volumes_box.max.z() = volumes_box.max.z() + height * 0.1f;
|
||||
volumes_box.min.z() = volumes_box.min.z() - height * 0.1f;
|
||||
|
||||
Camera camera;
|
||||
camera.set_type(camera_type);
|
||||
|
|
@ -5466,53 +5543,130 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||
//BoundingBoxf3 plate_box = plate->get_bounding_box(false);
|
||||
//plate_box.min.z() = 0.0;
|
||||
//plate_box.max.z() = 0.0;
|
||||
camera.zoom_to_box(volumes_box);
|
||||
const Vec3d& target = camera.get_target();
|
||||
double distance = camera.get_distance();
|
||||
camera.select_view("iso");
|
||||
|
||||
if (use_top_view) {
|
||||
float center_x = (plate_build_volume.max(0) + plate_build_volume.min(0))/2;
|
||||
float center_y = (plate_build_volume.max(1) + plate_build_volume.min(1))/2;
|
||||
float distance_z = plate_build_volume.max(2) - plate_build_volume.min(2);
|
||||
Vec3d center(center_x, center_y, 0.f);
|
||||
double zoom_ratio, scale_x, scale_y;
|
||||
|
||||
scale_x = ((double)thumbnail_data.width)/(plate_build_volume.max(0) - plate_build_volume.min(0));
|
||||
scale_y = ((double)thumbnail_data.height)/(plate_build_volume.max(1) - plate_build_volume.min(1));
|
||||
zoom_ratio = (scale_x <= scale_y)?scale_x:scale_y;
|
||||
camera.look_at(center + distance_z * Vec3d::UnitZ(), center, Vec3d::UnitY());
|
||||
camera.set_zoom(zoom_ratio);
|
||||
//camera.select_view("top");
|
||||
}
|
||||
else {
|
||||
camera.zoom_to_box(volumes_box);
|
||||
|
||||
const Vec3d& target = camera.get_target();
|
||||
double distance = camera.get_distance();
|
||||
camera.look_at(target - 0.707 * distance * Vec3d::UnitY() + 0.3 * distance * Vec3d::UnitZ(), target, Vec3d::UnitY() + Vec3d::UnitZ());
|
||||
}
|
||||
|
||||
camera.apply_view_matrix();
|
||||
|
||||
camera.apply_projection(plate_build_volume);
|
||||
|
||||
//GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (shader == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: shader is null, return directly");
|
||||
if (!for_picking && (shader == nullptr)) {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail with no picking: shader is null, return directly");
|
||||
return;
|
||||
}
|
||||
|
||||
//if (thumbnail_params.transparent_background)
|
||||
glsafe(::glClearColor(0.2f, 0.2f, 0.2f, 0.0f));
|
||||
if (for_picking)
|
||||
glsafe(::glClearColor(0.f, 0.f, 0.f, 0.f));
|
||||
else {
|
||||
//glsafe(::glClearColor(0.906f, 0.906f, 0.906f, 1.0f));
|
||||
//glsafe(::glClearColor(0.50f, 0.5f, 0.5f, 1.0f));
|
||||
//glsafe(::glClearColor(0.121568f, 0.121568f, 0.121568f, 1.0f));
|
||||
//glsafe(::glClearColor(0.17647f, 0.17647f, 0.17647f, 1.0f));
|
||||
glsafe(::glClearColor(0.906f, 0.906f, 0.906f, 1.0f));
|
||||
//glsafe(::glClearColor(0.37647f, 0.37647f, 0.37647f, 0.5f)); too lite
|
||||
//glsafe(::glClearColor(0.23529f, 0.26666f, 0.2745f, 1.0f));
|
||||
}
|
||||
|
||||
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("emission_factor", 0.0f);
|
||||
if (for_picking) {
|
||||
//if (OpenGLManager::can_multisample())
|
||||
// This flag is often ignored by NVIDIA drivers if rendering into a screen buffer.
|
||||
// glsafe(::glDisable(GL_MULTISAMPLE));
|
||||
|
||||
for (GLVolume* vol : visible_volumes) {
|
||||
//BBS set render color for thumbnails
|
||||
curr_color[0] = vol->color[0];
|
||||
curr_color[1] = vol->color[1];
|
||||
curr_color[2] = vol->color[2];
|
||||
curr_color[3] = vol->color[3];
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
shader->set_uniform("uniform_color", curr_color);
|
||||
//BBS set all volume to orange
|
||||
//shader->set_uniform("uniform_color", orange);
|
||||
/*if (plate_idx > 0) {
|
||||
shader->set_uniform("uniform_color", orange);
|
||||
static const GLfloat INV_255 = 1.0f / 255.0f;
|
||||
|
||||
// do not cull backfaces to show broken geometry, if any
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
|
||||
//glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
//glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
|
||||
|
||||
for (GLVolume* vol : visible_volumes) {
|
||||
// Object picking mode. Render the object with a color encoding the object index.
|
||||
// we reserve color = (0,0,0) for occluders (as the printbed)
|
||||
// so we shift volumes' id by 1 to get the proper color
|
||||
//BBS: remove the bed picking logic
|
||||
unsigned int id = vol->model_object_ID;
|
||||
//unsigned int id = 1 + volume.second.first;
|
||||
unsigned int r = (id & (0x000000FF << 0)) >> 0;
|
||||
unsigned int g = (id & (0x000000FF << 8)) >> 8;
|
||||
unsigned int b = (id & (0x000000FF << 16)) >> 16;
|
||||
unsigned int a = 0xFF;
|
||||
glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255));
|
||||
/*curr_color[0] = (GLfloat)r * INV_255;
|
||||
curr_color[1] = (GLfloat)g * INV_255;
|
||||
curr_color[2] = (GLfloat)b * INV_255;
|
||||
curr_color[3] = (GLfloat)a * INV_255;
|
||||
shader->set_uniform("uniform_color", curr_color);*/
|
||||
|
||||
bool is_active = vol->is_active;
|
||||
vol->is_active = true;
|
||||
vol->simple_render(nullptr, model_objects, extruder_colors);
|
||||
vol->is_active = is_active;
|
||||
}
|
||||
else {
|
||||
shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? orange : gray);
|
||||
}*/
|
||||
// the volume may have been deactivated by an active gizmo
|
||||
bool is_active = vol->is_active;
|
||||
vol->is_active = true;
|
||||
vol->simple_render(shader, model_objects, extruder_colors);
|
||||
vol->is_active = is_active;
|
||||
}
|
||||
|
||||
shader->stop_using();
|
||||
//glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
|
||||
//glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
|
||||
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
|
||||
//if (OpenGLManager::can_multisample())
|
||||
// glsafe(::glEnable(GL_MULTISAMPLE));
|
||||
}
|
||||
else {
|
||||
shader->start_using();
|
||||
shader->set_uniform("emission_factor", 0.1f);
|
||||
for (GLVolume* vol : visible_volumes) {
|
||||
//BBS set render color for thumbnails
|
||||
curr_color[0] = vol->color[0];
|
||||
curr_color[1] = vol->color[1];
|
||||
curr_color[2] = vol->color[2];
|
||||
curr_color[3] = vol->color[3];
|
||||
|
||||
shader->set_uniform("uniform_color", curr_color);
|
||||
shader->set_uniform("volume_world_matrix", vol->world_matrix());
|
||||
//BBS set all volume to orange
|
||||
//shader->set_uniform("uniform_color", orange);
|
||||
/*if (plate_idx > 0) {
|
||||
shader->set_uniform("uniform_color", orange);
|
||||
}
|
||||
else {
|
||||
shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? orange : gray);
|
||||
}*/
|
||||
// the volume may have been deactivated by an active gizmo
|
||||
bool is_active = vol->is_active;
|
||||
vol->is_active = true;
|
||||
vol->simple_render(shader, model_objects, extruder_colors);
|
||||
vol->is_active = is_active;
|
||||
}
|
||||
shader->stop_using();
|
||||
}
|
||||
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
|
||||
|
|
@ -5525,7 +5679,9 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: finished");
|
||||
}
|
||||
|
||||
void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type)
|
||||
void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
|
||||
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
|
||||
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view, bool for_picking)
|
||||
{
|
||||
thumbnail_data.set(w, h);
|
||||
if (!thumbnail_data.is_valid())
|
||||
|
|
@ -5576,7 +5732,7 @@ void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, uns
|
|||
glsafe(::glDrawBuffers(1, drawBufs));
|
||||
|
||||
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
|
||||
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type);
|
||||
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, use_top_view, for_picking);
|
||||
|
||||
if (multisample) {
|
||||
GLuint resolve_fbo;
|
||||
|
|
@ -5629,7 +5785,9 @@ void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, uns
|
|||
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail prepare: finished");
|
||||
}
|
||||
|
||||
void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type)
|
||||
void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
|
||||
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
|
||||
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view, bool for_picking)
|
||||
{
|
||||
thumbnail_data.set(w, h);
|
||||
if (!thumbnail_data.is_valid())
|
||||
|
|
@ -5679,7 +5837,7 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
|
|||
glsafe(::glDrawBuffers(1, drawBufs));
|
||||
|
||||
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type);
|
||||
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, use_top_view, for_picking);
|
||||
|
||||
if (multisample) {
|
||||
GLuint resolve_fbo;
|
||||
|
|
@ -6575,14 +6733,18 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
|||
else
|
||||
m_volumes.set_z_range(-FLT_MAX, FLT_MAX);
|
||||
|
||||
GLGizmosManager& gm = get_gizmos_manager();
|
||||
GLGizmoBase* current_gizmo = gm.get_current();
|
||||
if (m_canvas_type == CanvasAssembleView) {
|
||||
m_volumes.set_clipping_plane(m_gizmos.get_assemble_view_clipping_plane().get_data());
|
||||
}
|
||||
else if (current_gizmo && !current_gizmo->apply_clipping_plane()) {
|
||||
m_volumes.set_clipping_plane(ClippingPlane::ClipsNothing().get_data());
|
||||
}
|
||||
else {
|
||||
m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data());
|
||||
}
|
||||
//BBS: remove sinking logic
|
||||
//m_volumes.set_show_sinking_contours(! m_gizmos.is_hiding_instances());
|
||||
m_volumes.set_show_sinking_contours(! m_gizmos.is_hiding_instances());
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
|
||||
ECanvasType canvas_type = this->m_canvas_type;
|
||||
|
|
@ -7207,7 +7369,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
|
|||
|
||||
bool is_hovered = false;
|
||||
|
||||
m_sel_plate_toolbar.set_icon_size(80.0f * f_scale, 80.0f * f_scale);
|
||||
m_sel_plate_toolbar.set_icon_size(100.0f * f_scale, 100.0f * f_scale);
|
||||
|
||||
float button_width = m_sel_plate_toolbar.icon_width;
|
||||
float button_height = m_sel_plate_toolbar.icon_height;
|
||||
|
|
@ -7227,7 +7389,9 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
|
|||
ImVec4 button_active = ImVec4(0.12f, 0.56f, 0.92, 1.0f);
|
||||
ImVec4 button_hover = ImVec4(0.67f, 0.67f, 0.67, 1.0f);
|
||||
ImVec4 scroll_col = ImVec4(0.77f, 0.77f, 0.77f, 1.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.f, 0.f, 0.f, 1.0f));
|
||||
//ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.f, 0.f, 0.f, 1.0f));
|
||||
//use white text as the background switch to black
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, window_bg);
|
||||
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, window_bg);
|
||||
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, scroll_col);
|
||||
|
|
@ -7352,7 +7516,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
|
|||
if (item->selected) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, button_active);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_active);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(128.0f, 128.0f, 128.0f, 0.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.42f, 0.42f, 0.42f, 1.0f));
|
||||
|
|
@ -7558,11 +7722,12 @@ void GLCanvas3D::_render_paint_toolbar() const
|
|||
#if ENABLE_RETINA_GL
|
||||
float f_scale = m_retina_helper->get_scale_factor();
|
||||
#else
|
||||
float f_scale = 1.0;
|
||||
float f_scale = 1.0f;
|
||||
#endif
|
||||
int em_unit = wxGetApp().em_unit() / 10;
|
||||
|
||||
std::vector<std::string> colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
int extruder_num = colors.size();
|
||||
|
||||
std::vector<std::string> filament_text_first_line;
|
||||
std::vector<std::string> filament_text_second_line;
|
||||
{
|
||||
|
|
@ -7587,65 +7752,108 @@ void GLCanvas3D::_render_paint_toolbar() const
|
|||
}
|
||||
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
float canvas_w = float(get_canvas_size().get_width());
|
||||
int item_spacing = 8 * wxGetApp().toolbar_icon_scale() * f_scale;
|
||||
float button_size = GLToolbar::Default_Icons_Size * f_scale * wxGetApp().toolbar_icon_scale() + item_spacing;
|
||||
const float canvas_w = float(get_canvas_size().get_width());
|
||||
const ImVec2 button_size = ImVec2(64.0f, 48.0f) * f_scale * em_unit;
|
||||
const float spacing = 4.0f * em_unit * f_scale;
|
||||
const float return_button_margin = 130.0f * em_unit * f_scale;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(spacing, spacing));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, { 0.f, 0.f, 0.f, 0.4f });
|
||||
|
||||
imgui.set_next_window_pos(0.5f * canvas_w, 0, ImGuiCond_Always, 0.5f, 0.0f);
|
||||
imgui.begin(_L("Paint Toolbar"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar);
|
||||
float constraint_window_width = canvas_w - 2 * return_button_margin;
|
||||
ImGui::SetNextWindowSizeConstraints({ 0, 0 }, { constraint_window_width, FLT_MAX });
|
||||
imgui.begin(_L("Paint Toolbar"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||
|
||||
const float cursor_y = ImGui::GetCursorPosY();
|
||||
const ImVec2 arrow_button_size = ImVec2(0.375f * button_size.x, ImGui::GetWindowHeight());
|
||||
const ImRect left_arrow_button = ImRect(ImGui::GetCurrentWindow()->Pos, ImGui::GetCurrentWindow()->Pos + arrow_button_size);
|
||||
const ImRect right_arrow_button = ImRect(ImGui::GetCurrentWindow()->Pos + ImGui::GetWindowSize() - arrow_button_size, ImGui::GetCurrentWindow()->Pos + ImGui::GetWindowSize());
|
||||
ImU32 left_arrow_button_color = IM_COL32(0, 0, 0, 0.4f * 255);
|
||||
ImU32 right_arrow_button_color = IM_COL32(0, 0, 0, 0.4f * 255);
|
||||
ImU32 arrow_color = IM_COL32(255, 255, 255, 255);
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
ImGuiContext& context = *GImGui;
|
||||
bool disabled = !wxGetApp().plater()->can_fillcolor();
|
||||
unsigned char rgb[3];
|
||||
float cursor_y = ImGui::GetCursorPosY();
|
||||
|
||||
for (int i = 0; i < extruder_num; i++) {
|
||||
if (i > 0)
|
||||
ImGui::SameLine(0.0f, item_spacing);
|
||||
ImGui::SameLine();
|
||||
Slic3r::GUI::BitmapCache::parse_color(colors[i], rgb);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImColor(rgb[0], rgb[1], rgb[2]).Value);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor(rgb[0], rgb[1], rgb[2]).Value);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor(rgb[0], rgb[1], rgb[2]).Value);
|
||||
if (disabled)
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
if (ImGui::Button(("##filament_button" + std::to_string(i)).c_str(), ImVec2(button_size, button_size))) {
|
||||
wxPostEvent(m_canvas, IntEvent(EVT_GLTOOLBAR_FILLCOLOR, i + 1));
|
||||
if (ImGui::Button(("##filament_button" + std::to_string(i)).c_str(), button_size)) {
|
||||
if (!ImGui::IsMouseHoveringRect(left_arrow_button.Min, left_arrow_button.Max) && !ImGui::IsMouseHoveringRect(right_arrow_button.Min, right_arrow_button.Max))
|
||||
wxPostEvent(m_canvas, IntEvent(EVT_GLTOOLBAR_FILLCOLOR, i + 1));
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 20.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.00f, 1.00f, 1.00f, 1.00f));
|
||||
ImGui::TextUnformatted((boost::format(_u8L("Shortcut key %1%")) % (i + 1)).str().c_str());
|
||||
ImGui::PopStyleColor(1);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
if (ImGui::IsItemHovered() && i < 9) {
|
||||
if (!ImGui::IsMouseHoveringRect(left_arrow_button.Min, left_arrow_button.Max) && !ImGui::IsMouseHoveringRect(right_arrow_button.Min, right_arrow_button.Max)) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 20.0f * f_scale, 10.0f * f_scale });
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 3.0f * f_scale);
|
||||
imgui.tooltip(_L("Shortcut Key ") + std::to_string(i + 1), ImGui::GetFontSize() * 20.0f);
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
if (disabled)
|
||||
ImGui::PopItemFlag();
|
||||
}
|
||||
|
||||
float text_offset_y = 3.0f * f_scale;
|
||||
const float text_offset_y = 4.0f * em_unit * f_scale;
|
||||
for (int i = 0; i < extruder_num; i++){
|
||||
Slic3r::GUI::BitmapCache::parse_color(colors[i], rgb);
|
||||
float gray = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2];
|
||||
ImVec4 text_color = gray < 80 ? ImVec4(255, 255, 255, 255) : ImVec4(0, 0, 0, 255);
|
||||
|
||||
ImVec4 text_color = gray < 80 ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) : ImVec4(0, 0, 0, 1.0f);
|
||||
|
||||
imgui.push_bold_font();
|
||||
ImVec2 number_label_size = ImGui::CalcTextSize(std::to_string(i + 1).c_str());
|
||||
ImGui::SetCursorPosY(cursor_y + text_offset_y);
|
||||
ImGui::SetCursorPosX(item_spacing + i * (item_spacing + button_size) + (button_size - number_label_size.x) / 2);
|
||||
ImGui::SetCursorPosX(spacing + i * (spacing + button_size.x) + (button_size.x - number_label_size.x) / 2);
|
||||
ImGui::TextColored(text_color, std::to_string(i + 1).c_str());
|
||||
imgui.pop_bold_font();
|
||||
|
||||
ImVec2 filament_first_line_label_size = ImGui::CalcTextSize(filament_text_first_line[i].c_str());
|
||||
ImGui::SetCursorPosY(cursor_y + text_offset_y + number_label_size.y);
|
||||
ImGui::SetCursorPosX(item_spacing + i * (item_spacing + button_size) + (button_size - filament_first_line_label_size.x) / 2);
|
||||
ImGui::SetCursorPosX(spacing + i * (spacing + button_size.x) + (button_size.x - filament_first_line_label_size.x) / 2);
|
||||
ImGui::TextColored(text_color, filament_text_first_line[i].c_str());
|
||||
|
||||
ImVec2 filament_second_line_label_size = ImGui::CalcTextSize(filament_text_second_line[i].c_str());
|
||||
ImGui::SetCursorPosY(cursor_y + text_offset_y + number_label_size.y + filament_first_line_label_size.y);
|
||||
ImGui::SetCursorPosX(item_spacing + i * (item_spacing + button_size) + (button_size - filament_second_line_label_size.x) / 2);
|
||||
ImGui::SetCursorPosX(spacing + i * (spacing + button_size.x) + (button_size.x - filament_second_line_label_size.x) / 2);
|
||||
ImGui::TextColored(text_color, filament_text_second_line[i].c_str());
|
||||
}
|
||||
|
||||
if (ImGui::GetWindowWidth() == constraint_window_width) {
|
||||
if (ImGui::IsMouseHoveringRect(left_arrow_button.Min, left_arrow_button.Max)) {
|
||||
left_arrow_button_color = IM_COL32(0, 0, 0, 0.64f * 255);
|
||||
if (context.IO.MouseClicked[ImGuiMouseButton_Left]) {
|
||||
ImGui::SetScrollX(ImGui::GetScrollX() - button_size.x);
|
||||
imgui.set_requires_extra_frame();
|
||||
}
|
||||
}
|
||||
draw_list->AddRectFilled(left_arrow_button.Min, left_arrow_button.Max, left_arrow_button_color);
|
||||
ImGui::BBLRenderArrow(draw_list, left_arrow_button.GetCenter() - ImVec2(draw_list->_Data->FontSize, draw_list->_Data->FontSize) * 0.5f, arrow_color, ImGuiDir_Left, 2.0f);
|
||||
|
||||
if (ImGui::IsMouseHoveringRect(right_arrow_button.Min, right_arrow_button.Max)) {
|
||||
right_arrow_button_color = IM_COL32(0, 0, 0, 0.64f * 255);
|
||||
if (context.IO.MouseClicked[ImGuiMouseButton_Left]) {
|
||||
ImGui::SetScrollX(ImGui::GetScrollX() + button_size.x);
|
||||
imgui.set_requires_extra_frame();
|
||||
}
|
||||
}
|
||||
draw_list->AddRectFilled(right_arrow_button.Min, right_arrow_button.Max, right_arrow_button_color);
|
||||
ImGui::BBLRenderArrow(draw_list, right_arrow_button.GetCenter() - ImVec2(draw_list->_Data->FontSize, draw_list->_Data->FontSize) * 0.5f, arrow_color, ImGuiDir_Right, 2.0f);
|
||||
}
|
||||
|
||||
imgui.end();
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
//BBS
|
||||
|
|
@ -7671,7 +7879,7 @@ void GLCanvas3D::_render_assemble_control() const
|
|||
const float item_spacing = imgui->get_item_spacing().x;
|
||||
ImVec2 window_padding = ImGui::GetStyle().WindowPadding;
|
||||
|
||||
imgui->set_next_window_pos(canvas_w / 2, canvas_h - 13.0f * get_scale(), ImGuiCond_Always, 0.5f, 1.0f);
|
||||
imgui->set_next_window_pos(canvas_w / 2, canvas_h - 10.0f * get_scale(), ImGuiCond_Always, 0.5f, 1.0f);
|
||||
imgui->begin(_L("Assemble Control"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
|
|
@ -7740,24 +7948,18 @@ void GLCanvas3D::_render_assemble_info() const
|
|||
ImGuiWrapper* imgui = wxGetApp().imgui();
|
||||
auto canvas_w = float(get_canvas_size().get_width());
|
||||
auto canvas_h = float(get_canvas_size().get_height());
|
||||
float window_height = 130.0f;
|
||||
float space_size = imgui->get_style_scaling() * 8.0f;
|
||||
float caption_max = imgui->calc_text_size(_L("Total Volume:")).x + 3 * space_size;
|
||||
char buf[3][64];
|
||||
float merged_max = 0.0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ImGui::DataTypeFormatString(buf[i], IM_ARRAYSIZE(buf[i]), ImGuiDataType_Double, (void *) &volumes_bounding_box().size()(i), "%.2f");
|
||||
merged_max += ImGui::CalcTextSize(buf[i]).x;
|
||||
if (i < 2) merged_max += ImGui::CalcTextSize(" x ").x;
|
||||
}
|
||||
float window_width = merged_max + caption_max + ImGui::GetFrameHeight();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImFont* font = io.Fonts->Fonts[0];
|
||||
float origScale = font->Scale;
|
||||
font->Scale = 1.2;
|
||||
ImGui::PushFont(font);
|
||||
ImGui::PopFont();
|
||||
imgui->set_next_window_pos(canvas_w - window_width, 0.0f, ImGuiCond_Always, 0, 0);
|
||||
float margin = 10.0f * get_scale();
|
||||
imgui->set_next_window_pos(canvas_w - margin, canvas_h - margin, ImGuiCond_Always, 1.0f, 1.0f);
|
||||
ImGuiWrapper::push_toolbar_style(get_scale());
|
||||
imgui->begin(_L("Assembly Info"), ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
|
||||
font->Scale = origScale;
|
||||
|
|
@ -7923,8 +8125,7 @@ void GLCanvas3D::_render_sla_slices()
|
|||
|
||||
void GLCanvas3D::_render_selection_sidebar_hints() const
|
||||
{
|
||||
//BBS do not render sidebar hints
|
||||
//m_selection.render_sidebar_hints(m_sidebar_field, m_gizmos.get_uniform_scaling());
|
||||
m_selection.render_sidebar_hints(m_sidebar_field, m_gizmos.get_uniform_scaling());
|
||||
}
|
||||
|
||||
void GLCanvas3D::_update_volumes_hover_state()
|
||||
|
|
@ -8654,7 +8855,10 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning)
|
|||
else {
|
||||
if (wxGetApp().is_editor()) {
|
||||
if (current_printer_technology() != ptSLA)
|
||||
show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed();
|
||||
if (warning == EWarning::ToolpathOutside)
|
||||
show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed();
|
||||
else if (warning==EWarning::GCodeConflict)
|
||||
show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.m_conflict_result.has_value();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8693,6 +8897,18 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
|
|||
std::string text;
|
||||
ErrorType error = ErrorType::PLATER_WARNING;
|
||||
switch (warning) {
|
||||
case EWarning::GCodeConflict: {
|
||||
if (!m_gcode_viewer.m_conflict_result) { break; }
|
||||
std::string objName1 = m_gcode_viewer.m_conflict_result.value()._objName1;
|
||||
std::string objName2 = m_gcode_viewer.m_conflict_result.value()._objName2;
|
||||
double height = m_gcode_viewer.m_conflict_result.value()._height;
|
||||
int layer = m_gcode_viewer.m_conflict_result.value().layer;
|
||||
text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s).")) % layer %
|
||||
height % objName1 % objName2)
|
||||
.str();
|
||||
error = ErrorType::SLICING_ERROR;
|
||||
break;
|
||||
}
|
||||
case EWarning::ObjectOutside: text = _u8L("An object is layed over the boundary of plate."); break;
|
||||
case EWarning::ToolpathOutside: text = _u8L("A G-code path goes beyond the boundary of plate."); error = ErrorType::SLICING_ERROR; break;
|
||||
// BBS: remove _u8L() for SLA
|
||||
|
|
@ -8708,6 +8924,26 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
|
|||
if (!wxGetApp().plater())
|
||||
return;
|
||||
auto& notification_manager = *wxGetApp().plater()->get_notification_manager();
|
||||
|
||||
if (warning == EWarning::GCodeConflict && m_gcode_viewer.m_conflict_result) {
|
||||
const PrintObject *obj2 = reinterpret_cast<const PrintObject *>(m_gcode_viewer.m_conflict_result.value()._obj2);
|
||||
auto mo = obj2->model_object();
|
||||
ObjectID id = mo->id();
|
||||
auto action_fn = [id](wxEvtHandler *) {
|
||||
auto &objects = wxGetApp().model().objects;
|
||||
auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end();
|
||||
if (iter != objects.end()) {
|
||||
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
|
||||
wxGetApp().obj_list()->select_items({{*iter, nullptr}});
|
||||
}
|
||||
return false;
|
||||
};
|
||||
auto hypertext = _u8L("Jump to");
|
||||
hypertext += std::string(" [") + mo->name + "]";
|
||||
notification_manager.push_notification(NotificationType::PlaterError, NotificationManager::NotificationLevel::ErrorNotificationLevel, _u8L("ERROR:") + "\n" + text,
|
||||
hypertext, action_fn);
|
||||
return;
|
||||
}
|
||||
switch (error)
|
||||
{
|
||||
case PLATER_WARNING:
|
||||
|
|
|
|||
|
|
@ -334,6 +334,7 @@ class GLCanvas3D
|
|||
Vec3d scene_position;
|
||||
Drag drag;
|
||||
bool ignore_left_up;
|
||||
bool ignore_right_up;
|
||||
|
||||
Mouse();
|
||||
|
||||
|
|
@ -371,7 +372,8 @@ class GLCanvas3D
|
|||
ToolpathOutside,
|
||||
SlaSupportsOutside,
|
||||
SomethingNotShown,
|
||||
ObjectClashed
|
||||
ObjectClashed,
|
||||
GCodeConflict
|
||||
};
|
||||
|
||||
class RenderStats
|
||||
|
|
@ -832,13 +834,21 @@ public:
|
|||
|
||||
// printable_only == false -> render also non printable volumes as grayed
|
||||
// parts_only == false -> render also sla support and pad
|
||||
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type);
|
||||
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type);
|
||||
static void render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type);
|
||||
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
|
||||
Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
|
||||
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
|
||||
const GLVolumeCollection& volumes, Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
|
||||
static void render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects,
|
||||
const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
|
||||
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
|
||||
// render thumbnail using an off-screen framebuffer
|
||||
static void render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type);
|
||||
static void render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
|
||||
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
|
||||
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
|
||||
// render thumbnail using an off-screen framebuffer when GLEW_EXT_framebuffer_object is supported
|
||||
static void render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type);
|
||||
static void render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
|
||||
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
|
||||
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
|
||||
|
||||
//BBS use gcoder viewer render calibration thumbnails
|
||||
void render_calibration_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params);
|
||||
|
|
@ -1048,6 +1058,9 @@ public:
|
|||
|
||||
bool make_current_for_postinit();
|
||||
|
||||
//BBS
|
||||
Points estimate_wipe_tower_points(int plate_index, bool global = true) const;
|
||||
|
||||
private:
|
||||
bool _is_shown_on_screen() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ std::pair<bool, std::string> GLShadersManager::init()
|
|||
|
||||
// used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview
|
||||
valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" });
|
||||
//used to render thumbnail
|
||||
valid &= append_shader("thumbnail", { "thumbnail.vs", "thumbnail.fs" });
|
||||
// used to render first layer for calibration
|
||||
valid &= append_shader("cali", { "cali.vs", "cali.fs"});
|
||||
// used to render printbed
|
||||
|
|
@ -44,6 +46,7 @@ std::pair<bool, std::string> GLShadersManager::init()
|
|||
valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" });
|
||||
// used to render extrusion and travel paths as lines in gcode preview
|
||||
valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" });
|
||||
|
||||
// used to render objects in 3d editor
|
||||
//if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) {
|
||||
if (0) {
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ const std::string& shortkey_ctrl_prefix()
|
|||
#ifdef __APPLE__
|
||||
"⌘+"
|
||||
#else
|
||||
"Ctrl+"
|
||||
_u8L("Ctrl+")
|
||||
#endif
|
||||
;
|
||||
return str;
|
||||
|
|
@ -221,8 +221,10 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||
|
||||
void show_error(wxWindow* parent, const wxString& message, bool monospaced_font)
|
||||
{
|
||||
ErrorDialog msg(parent, message, monospaced_font);
|
||||
msg.ShowModal();
|
||||
wxGetApp().CallAfter([=] {
|
||||
ErrorDialog msg(parent, message, monospaced_font);
|
||||
msg.ShowModal();
|
||||
});
|
||||
}
|
||||
|
||||
void show_error(wxWindow* parent, const char* message, bool monospaced_font)
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include "../Utils/Process.hpp"
|
||||
#include "../Utils/MacDarkMode.hpp"
|
||||
#include "../Utils/Http.hpp"
|
||||
#include "../Utils/UndoRedo.hpp"
|
||||
#include "slic3r/Config/Snapshot.hpp"
|
||||
#include "Preferences.hpp"
|
||||
#include "Tab.hpp"
|
||||
|
|
@ -951,28 +952,45 @@ static void generic_exception_handle()
|
|||
} catch (const std::bad_alloc& ex) {
|
||||
// bad_alloc in main thread is most likely fatal. Report immediately to the user (wxLogError would be delayed)
|
||||
// and terminate the app so it is at least certain to happen now.
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("std::bad_alloc exception: %1%") % ex.what();
|
||||
flush_logs();
|
||||
wxString errmsg = wxString::Format(_L("OrcaSlicer will terminate because of running out of memory."
|
||||
"It may be a bug. It will be appreciated if you report the issue to our team."));
|
||||
wxMessageBox(errmsg + "\n\n" + wxString(ex.what()), _L("Fatal error"), wxOK | wxICON_ERROR);
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("std::bad_alloc exception: %1%") % ex.what();
|
||||
|
||||
std::terminate();
|
||||
//throw;
|
||||
} catch (const boost::io::bad_format_string& ex) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what();
|
||||
flush_logs();
|
||||
wxString errmsg = _L("OrcaSlicer will terminate because of a localization error. "
|
||||
"It will be appreciated if you report the specific scenario this issue happened.");
|
||||
wxMessageBox(errmsg + "\n\n" + wxString(ex.what()), _L("Critical error"), wxOK | wxICON_ERROR);
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what();
|
||||
std::terminate();
|
||||
//throw;
|
||||
} catch (const std::exception& ex) {
|
||||
wxLogError(format_wxstr(_L("OrcaSlicer got an unhandled exception: %1%"), ex.what()));
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what();
|
||||
flush_logs();
|
||||
throw;
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
|
||||
static std::vector<std::string> split_str(const std::string& src, const std::string& separator)
|
||||
{
|
||||
size_t pos;
|
||||
size_t start_pos = 0;
|
||||
vector<string> result_str;
|
||||
while ((pos = src.find(separator, start_pos)) != string::npos)
|
||||
{
|
||||
result_str.emplace_back(src.substr(start_pos, pos - start_pos));
|
||||
start_pos = pos + separator.size();
|
||||
}
|
||||
result_str.emplace_back(src.substr(start_pos, src.size() - pos - separator.size()));
|
||||
return result_str;
|
||||
}
|
||||
|
||||
void GUI_App::post_init()
|
||||
{
|
||||
assert(initialized());
|
||||
|
|
@ -981,29 +999,55 @@ void GUI_App::post_init()
|
|||
|
||||
bool switch_to_3d = false;
|
||||
if (!this->init_params->input_files.empty()) {
|
||||
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", init with input files, size %1%, input_gcode %2%")
|
||||
%this->init_params->input_files.size() %this->init_params->input_gcode;
|
||||
switch_to_3d = true;
|
||||
if (this->init_params->input_gcode) {
|
||||
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
|
||||
plater_->select_view_3D("3D");
|
||||
this->plater()->load_gcode(from_u8(this->init_params->input_files.front()));
|
||||
|
||||
|
||||
|
||||
if (this->init_params->input_files.size() == 1 &&
|
||||
boost::starts_with(this->init_params->input_files.front(), "bambustudio://open")) {
|
||||
auto input_str_arr = split_str(this->init_params->input_files.front(), "bambustudio://open/?file=");
|
||||
|
||||
std::string download_origin_url;
|
||||
for (auto input_str:input_str_arr) {
|
||||
if (!input_str.empty()) download_origin_url = input_str;
|
||||
}
|
||||
|
||||
std::string download_file_url = url_decode(download_origin_url);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << download_file_url;
|
||||
if (!download_file_url.empty() && ( boost::starts_with(download_file_url, "http://") || boost::starts_with(download_file_url, "https://")) ) {
|
||||
request_model_download(download_origin_url);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
|
||||
plater_->select_view_3D("3D");
|
||||
const std::vector<size_t> res = this->plater()->load_files(this->init_params->input_files);
|
||||
if (!res.empty()) {
|
||||
if (this->init_params->input_files.size() == 1) {
|
||||
// Update application titlebar when opening a project file
|
||||
const std::string& filename = this->init_params->input_files.front();
|
||||
//BBS: remove amf logic as project
|
||||
if (boost::algorithm::iends_with(filename, ".3mf"))
|
||||
this->plater()->set_project_filename(from_u8(filename));
|
||||
switch_to_3d = true;
|
||||
if (this->init_params->input_gcode) {
|
||||
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
|
||||
plater_->select_view_3D("3D");
|
||||
this->plater()->load_gcode(from_u8(this->init_params->input_files.front()));
|
||||
}
|
||||
else {
|
||||
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
|
||||
plater_->select_view_3D("3D");
|
||||
Plater::TakeSnapshot snapshot(this->plater(), "Load Project", UndoRedo::SnapshotType::ProjectSeparator);
|
||||
const std::vector<size_t> res = this->plater()->load_files(this->init_params->input_files);
|
||||
if (!res.empty()) {
|
||||
if (this->init_params->input_files.size() == 1) {
|
||||
// Update application titlebar when opening a project file
|
||||
const std::string& filename = this->init_params->input_files.front();
|
||||
this->plater()->up_to_date(true, false);
|
||||
this->plater()->up_to_date(true, true);
|
||||
//BBS: remove amf logic as project
|
||||
if (boost::algorithm::iends_with(filename, ".3mf"))
|
||||
this->plater()->set_project_filename(from_u8(filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#if BBL_HAS_FIRST_PAGE
|
||||
bool slow_bootup = false;
|
||||
if (app_config->get("slow_bootup") == "true") {
|
||||
|
|
@ -1017,9 +1061,9 @@ void GUI_App::post_init()
|
|||
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
|
||||
plater_->select_view_3D("3D");
|
||||
//BBS init the opengl resource here
|
||||
#ifdef __linux__
|
||||
//#ifdef __linux__
|
||||
if (plater_->canvas3D()->get_wxglcanvas()->IsShownOnScreen()&&plater_->canvas3D()->make_current_for_postinit()) {
|
||||
#endif
|
||||
//#endif
|
||||
Size canvas_size = plater_->canvas3D()->get_canvas_size();
|
||||
wxGetApp().imgui()->set_display_size(static_cast<float>(canvas_size.get_width()), static_cast<float>(canvas_size.get_height()));
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", start to init opengl";
|
||||
|
|
@ -1039,9 +1083,12 @@ void GUI_App::post_init()
|
|||
plater_->canvas3D()->render(false);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished rendering a first frame for test";
|
||||
}
|
||||
#ifdef __linux__
|
||||
//#ifdef __linux__
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << "Found glcontext not ready, postpone the init";
|
||||
}
|
||||
//#endif
|
||||
if (is_editor())
|
||||
mainframe->select_tab(size_t(0));
|
||||
mainframe->Thaw();
|
||||
|
|
@ -1123,7 +1170,8 @@ void GUI_App::post_init()
|
|||
std::string http_url = get_http_url(app_config->get_country_code());
|
||||
std::string language = GUI::into_u8(current_language_code());
|
||||
std::string network_ver = Slic3r::NetworkAgent::get_version();
|
||||
this->preset_updater->sync(http_url, language, network_ver, preset_bundle);
|
||||
bool sys_preset = app_config->get("sync_system_preset") == "true";
|
||||
this->preset_updater->sync(http_url, language, network_ver, sys_preset ? preset_bundle : nullptr);
|
||||
|
||||
//BBS: check new version
|
||||
this->check_new_version_sf();
|
||||
|
|
@ -1296,12 +1344,40 @@ std::string GUI_App::get_http_url(std::string country_code)
|
|||
return url;
|
||||
}
|
||||
|
||||
std::string GUI_App::get_model_http_url(std::string country_code)
|
||||
{
|
||||
std::string url;
|
||||
if (country_code == "US") {
|
||||
url = "https://makerhub.bambu-lab.com/";
|
||||
}
|
||||
else if (country_code == "CN") {
|
||||
url = "https://makerhub.bambu-lab.com/zh/";
|
||||
}
|
||||
else if (country_code == "ENV_CN_DEV") {
|
||||
url = "https://makerhub-dev.bambu-lab.com/";
|
||||
}
|
||||
else if (country_code == "ENV_CN_QA") {
|
||||
url = "https://makerhub-qa.bambu-lab.com/";
|
||||
}
|
||||
else if (country_code == "ENV_CN_PRE") {
|
||||
url = "https://makerhub-pre.bambu-lab.com/";
|
||||
}
|
||||
else {
|
||||
url = "https://makerhub.bambu-lab.com/";
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
std::string GUI_App::get_plugin_url(std::string name, std::string country_code)
|
||||
{
|
||||
std::string url = get_http_url(country_code);
|
||||
|
||||
std::string curr_version = SLIC3R_VERSION;
|
||||
std::string using_version = curr_version.substr(0, 9) + "00";
|
||||
if (name == "cameratools")
|
||||
using_version = curr_version.substr(0, 6) + "00.00";
|
||||
url += (boost::format("?slicer/%1%/cloud=%2%") % name % using_version).str();
|
||||
//url += (boost::format("?slicer/plugins/cloud=%1%") % "01.01.00.00").str();
|
||||
return url;
|
||||
|
|
@ -1325,10 +1401,19 @@ static std::string decode(std::string const& extra, std::string const& path = {}
|
|||
int GUI_App::download_plugin(std::string name, std::string package_name, InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
|
||||
{
|
||||
int result = 0;
|
||||
json j;
|
||||
std::string err_msg;
|
||||
|
||||
// get country_code
|
||||
AppConfig* app_config = wxGetApp().app_config;
|
||||
if (!app_config)
|
||||
if (!app_config) {
|
||||
j["result"] = "failed";
|
||||
j["error_msg"] = "app_config is nullptr";
|
||||
if (m_agent) {
|
||||
m_agent->track_event("networkplugin_download", j.dump());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "[download_plugin]: enter";
|
||||
m_networking_cancel_update = false;
|
||||
|
|
@ -1388,21 +1473,32 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
|
|||
;
|
||||
}
|
||||
}).on_error(
|
||||
[&result](std::string body, std::string error, unsigned int status) {
|
||||
[&result, &err_msg](std::string body, std::string error, unsigned int status) {
|
||||
BOOST_LOG_TRIVIAL(error) << "[download_plugin 1] on_error: " << error<<", body = " << body;
|
||||
err_msg += "[download_plugin 1] on_error: " + error + ", body = " + body;
|
||||
result = -1;
|
||||
}).perform_sync();
|
||||
|
||||
bool cancel = false;
|
||||
if (result < 0) {
|
||||
j["result"] = "failed";
|
||||
j["error_msg"] = err_msg;
|
||||
if (m_agent) {
|
||||
m_agent->track_event("networkplugin_download", j.dump());
|
||||
}
|
||||
if (pro_fn) pro_fn(InstallStatusDownloadFailed, 0, cancel);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
if (download_url.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "[download_plugin 1]: no availaible plugin found for this app version: " << SLIC3R_VERSION;
|
||||
BOOST_LOG_TRIVIAL(info) << "[download_plugin 1]: no available plugin found for this app version: " << SLIC3R_VERSION;
|
||||
if (pro_fn) pro_fn(InstallStatusDownloadFailed, 0, cancel);
|
||||
j["result"] = "failed";
|
||||
j["error_msg"] = "[download_plugin 1]: no available plugin found for this app version: " + std::string(SLIC3R_VERSION);
|
||||
if (m_agent) {
|
||||
m_agent->track_event("networkplugin_download", j.dump());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else if (pro_fn) {
|
||||
|
|
@ -1411,6 +1507,11 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
|
|||
|
||||
if (m_networking_cancel_update || cancel) {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("[download_plugin 1]: %1%, cancelled by user") % __LINE__;
|
||||
j["result"] = "failed";
|
||||
j["error_msg"] = (boost::format("[download_plugin 1]: %1%, cancelled by user") % __LINE__).str();
|
||||
if (m_agent) {
|
||||
m_agent->track_event("networkplugin_download", j.dump());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "[download_plugin] get_url = " << download_url;
|
||||
|
|
@ -1419,7 +1520,7 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
|
|||
Slic3r::Http http = Slic3r::Http::get(download_url);
|
||||
int reported_percent = 0;
|
||||
http.on_progress(
|
||||
[this, &pro_fn, cancel_fn, &result, &reported_percent](Slic3r::Http::Progress progress, bool& cancel) {
|
||||
[this, &pro_fn, cancel_fn, &result, &reported_percent, &err_msg](Slic3r::Http::Progress progress, bool& cancel) {
|
||||
int percent = 0;
|
||||
if (progress.dltotal != 0)
|
||||
percent = progress.dlnow * 50 / progress.dltotal;
|
||||
|
|
@ -1434,8 +1535,10 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
|
|||
if (cancel_fn())
|
||||
cancel = true;
|
||||
|
||||
if (cancel)
|
||||
if (cancel) {
|
||||
err_msg += "[download_plugin] cancel";
|
||||
result = -1;
|
||||
}
|
||||
})
|
||||
.on_complete([&pro_fn, tmp_path, target_file_path](std::string body, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(info) << "[download_plugin 2] completed";
|
||||
|
|
@ -1447,13 +1550,19 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install
|
|||
fs::rename(tmp_path, target_file_path);
|
||||
if (pro_fn) pro_fn(InstallStatusDownloadCompleted, 80, cancel);
|
||||
})
|
||||
.on_error([&pro_fn, &result](std::string body, std::string error, unsigned int status) {
|
||||
.on_error([&pro_fn, &result, &err_msg](std::string body, std::string error, unsigned int status) {
|
||||
bool cancel = false;
|
||||
if (pro_fn) pro_fn(InstallStatusDownloadFailed, 0, cancel);
|
||||
BOOST_LOG_TRIVIAL(error) << "[download_plugin 2] on_error: " << error<<", body = " << body;
|
||||
err_msg += "[download_plugin 2] on_error: " + error + ", body = " + body;
|
||||
result = -1;
|
||||
});
|
||||
http.perform_sync();
|
||||
j["result"] = result < 0 ? "failed" : "success";
|
||||
j["error_msg"] = err_msg;
|
||||
if (m_agent) {
|
||||
m_agent->track_event("networkplugin_download", j.dump());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1605,6 +1714,8 @@ void GUI_App::restart_networking()
|
|||
mainframe->refresh_plugin_tips();
|
||||
if (plater_)
|
||||
plater_->get_notification_manager()->bbl_close_plugin_install_notification();
|
||||
|
||||
if (app_config->get("sync_user_preset") == "true") { start_sync_user_preset(); }
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(" exit, m_agent=%1%")%m_agent;
|
||||
}
|
||||
|
|
@ -1730,7 +1841,7 @@ void GUI_App::init_networking_callbacks()
|
|||
} else if (state == ConnectStatus::ConnectStatusFailed) {
|
||||
obj->set_access_code("");
|
||||
obj->set_user_access_code("");
|
||||
m_device_manager->set_selected_machine("");
|
||||
m_device_manager->set_selected_machine("", true);
|
||||
wxString text;
|
||||
if (msg == "5") {
|
||||
text = wxString::Format(_L("Incorrect password"));
|
||||
|
|
@ -1741,7 +1852,7 @@ void GUI_App::init_networking_callbacks()
|
|||
}
|
||||
event.SetInt(0);
|
||||
} else if (state == ConnectStatus::ConnectStatusLost) {
|
||||
m_device_manager->set_selected_machine("");
|
||||
m_device_manager->set_selected_machine("", true);
|
||||
event.SetInt(0);
|
||||
BOOST_LOG_TRIVIAL(info) << "set_on_local_connect_fn: state = lost";
|
||||
} else {
|
||||
|
|
@ -1932,6 +2043,19 @@ void GUI_App::init_app_config()
|
|||
m_datadir_redefined = true;
|
||||
}
|
||||
|
||||
// start log here
|
||||
std::time_t t = std::time(0);
|
||||
std::tm * now_time = std::localtime(&t);
|
||||
std::stringstream buf;
|
||||
buf << std::put_time(now_time, "debug_%a_%b_%d_%H_%M_%S_");
|
||||
buf << get_current_pid() << ".log";
|
||||
std::string log_filename = buf.str();
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
set_log_path_and_level(log_filename, 5);
|
||||
#else
|
||||
set_log_path_and_level(log_filename, 3);
|
||||
#endif
|
||||
|
||||
//BBS: remove GCodeViewer as seperate APP logic
|
||||
if (!app_config)
|
||||
app_config = new AppConfig();
|
||||
|
|
@ -1983,6 +2107,7 @@ std::map<std::string, std::string> GUI_App::get_extra_header()
|
|||
{
|
||||
std::map<std::string, std::string> extra_headers;
|
||||
extra_headers.insert(std::make_pair("X-BBL-Client-Type", "slicer"));
|
||||
extra_headers.insert(std::make_pair("X-BBL-Client-Name", SLIC3R_APP_NAME));
|
||||
extra_headers.insert(std::make_pair("X-BBL-Client-Version", VersionInfo::convert_full_version(SLIC3R_VERSION)));
|
||||
#if defined(__WINDOWS__)
|
||||
extra_headers.insert(std::make_pair("X-BBL-OS-Type", "windows"));
|
||||
|
|
@ -2055,19 +2180,6 @@ bool GUI_App::OnInit()
|
|||
|
||||
bool GUI_App::on_init_inner()
|
||||
{
|
||||
//start log here
|
||||
std::time_t t = std::time(0);
|
||||
std::tm* now_time = std::localtime(&t);
|
||||
std::stringstream buf;
|
||||
buf << std::put_time(now_time, "debug_%a_%b_%d_%H_%M_%S_");
|
||||
buf << get_current_pid() << ".log";
|
||||
std::string log_filename = buf.str();
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
set_log_path_and_level(log_filename, 5);
|
||||
#else
|
||||
set_log_path_and_level(log_filename, 3);
|
||||
#endif
|
||||
|
||||
// Set initialization of image handlers before any UI actions - See GH issue #7469
|
||||
wxInitAllImageHandlers();
|
||||
#ifdef NDEBUG
|
||||
|
|
@ -2426,7 +2538,7 @@ bool GUI_App::on_init_inner()
|
|||
|
||||
sidebar().obj_list()->init();
|
||||
//sidebar().aux_list()->init_auxiliary();
|
||||
mainframe->m_auxiliary->init_auxiliary();
|
||||
//mainframe->m_auxiliary->init_auxiliary();
|
||||
|
||||
// update_mode(); // !!! do that later
|
||||
SetTopWindow(mainframe);
|
||||
|
|
@ -2493,12 +2605,18 @@ bool GUI_App::on_init_inner()
|
|||
if (m_studio_active != curr_studio_active) {
|
||||
if (curr_studio_active) {
|
||||
BOOST_LOG_TRIVIAL(info) << "studio is active, start to subscribe";
|
||||
if (m_agent)
|
||||
if (m_agent) {
|
||||
json j = json::object();
|
||||
m_agent->start_subscribe("app");
|
||||
m_agent->track_event("mqtt_active", j.dump());
|
||||
}
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "studio is inactive, stop to subscribe";
|
||||
if (m_agent)
|
||||
if (m_agent) {
|
||||
json j = json::object();
|
||||
m_agent->stop_subscribe("app");
|
||||
m_agent->track_event("mqtt_inactive", j.dump());
|
||||
}
|
||||
}
|
||||
m_studio_active = curr_studio_active;
|
||||
}
|
||||
|
|
@ -2528,6 +2646,11 @@ bool GUI_App::on_init_inner()
|
|||
this->mainframe->register_win32_callbacks();
|
||||
#endif
|
||||
this->post_init();
|
||||
|
||||
if (!m_download_file_url.empty()) {
|
||||
request_model_download(m_download_file_url);
|
||||
m_download_file_url = "";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -2741,8 +2864,9 @@ void GUI_App::init_label_colours()
|
|||
m_color_label_default = is_dark_mode ? wxColour(250, 250, 250) : m_color_label_sys; // wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
m_color_highlight_label_default = is_dark_mode ? wxColour(230, 230, 230): wxSystemSettings::GetColour(/*wxSYS_COLOUR_HIGHLIGHTTEXT*/wxSYS_COLOUR_WINDOWTEXT);
|
||||
m_color_highlight_default = is_dark_mode ? wxColour(78, 78, 78) : wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT);
|
||||
m_color_hovered_btn_label = is_dark_mode ? wxColour(253, 111, 40) : wxColour(252, 77, 1);
|
||||
m_color_selected_btn_bg = is_dark_mode ? wxColour(95, 73, 62) : wxColour(228, 220, 216);
|
||||
m_color_hovered_btn_label = is_dark_mode ? wxColour(255, 255, 254) : wxColour(0,0,0);
|
||||
m_color_default_btn_label = is_dark_mode ? wxColour(255, 255, 254): wxColour(0,0,0);
|
||||
m_color_selected_btn_bg = is_dark_mode ? wxColour(84, 84, 91) : wxColour(206, 206, 206);
|
||||
#else
|
||||
m_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
#endif
|
||||
|
|
@ -2771,11 +2895,59 @@ void GUI_App::update_label_colours()
|
|||
tab->update_label_colours();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static bool is_focused(HWND hWnd)
|
||||
{
|
||||
HWND hFocusedWnd = ::GetFocus();
|
||||
return hFocusedWnd && hWnd == hFocusedWnd;
|
||||
}
|
||||
|
||||
static bool is_default(wxWindow* win)
|
||||
{
|
||||
wxTopLevelWindow* tlw = find_toplevel_parent(win);
|
||||
if (!tlw)
|
||||
return false;
|
||||
|
||||
return win == tlw->GetDefaultItem();
|
||||
}
|
||||
#endif
|
||||
|
||||
void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool just_font/* = false*/)
|
||||
{
|
||||
if (wxButton *btn = dynamic_cast<wxButton *>(window)) {
|
||||
if (wxButton *btn = dynamic_cast<wxButton*>(window)) {
|
||||
if (btn->GetWindowStyleFlag() & wxBU_AUTODRAW)
|
||||
return;
|
||||
else {
|
||||
#ifdef _WIN32
|
||||
if (btn->GetId() == wxID_OK || btn->GetId() == wxID_CANCEL) {
|
||||
bool is_focused_button = false;
|
||||
bool is_default_button = false;
|
||||
|
||||
if (!(btn->GetWindowStyle() & wxNO_BORDER)) {
|
||||
btn->SetWindowStyle(btn->GetWindowStyle() | wxNO_BORDER);
|
||||
highlited = true;
|
||||
}
|
||||
|
||||
auto mark_button = [this, btn, highlited](const bool mark) {
|
||||
btn->SetBackgroundColour(mark ? m_color_selected_btn_bg : highlited ? m_color_highlight_default : m_color_window_default);
|
||||
btn->SetForegroundColour(mark ? m_color_hovered_btn_label :m_color_default_btn_label);
|
||||
btn->Refresh();
|
||||
btn->Update();
|
||||
};
|
||||
|
||||
// hovering
|
||||
btn->Bind(wxEVT_ENTER_WINDOW, [mark_button](wxMouseEvent& event) { mark_button(true); event.Skip(); });
|
||||
btn->Bind(wxEVT_LEAVE_WINDOW, [mark_button, btn](wxMouseEvent& event) { mark_button(is_focused(btn->GetHWND())); event.Skip(); });
|
||||
// focusing
|
||||
btn->Bind(wxEVT_SET_FOCUS, [mark_button](wxFocusEvent& event) { mark_button(true); event.Skip(); });
|
||||
btn->Bind(wxEVT_KILL_FOCUS, [mark_button](wxFocusEvent& event) { mark_button(false); event.Skip(); });
|
||||
|
||||
is_focused_button = is_focused(btn->GetHWND());
|
||||
is_default_button = is_default(btn);
|
||||
mark_button(is_focused_button);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (Button* btn = dynamic_cast<Button*>(window)) {
|
||||
|
|
@ -3055,7 +3227,7 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
|
|||
// Propagate model objects to object list.
|
||||
sidebar().obj_list()->init();
|
||||
//sidebar().aux_list()->init_auxiliary();
|
||||
mainframe->m_auxiliary->init_auxiliary();
|
||||
//mainframe->m_auxiliary->init_auxiliary();
|
||||
SetTopWindow(mainframe);
|
||||
|
||||
dlg.Update(30, _L("Rebuild") + dots);
|
||||
|
|
@ -3085,6 +3257,21 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
|
|||
// config_wizard_startup(true);
|
||||
// });
|
||||
|
||||
//show publish button
|
||||
if (m_agent && m_agent->is_user_login() && mainframe) {
|
||||
int identifier;
|
||||
int result = m_agent->get_user_info(&identifier);
|
||||
auto publish_identifier = identifier & 1;
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
if (result == 0 && publish_identifier >= 0) {
|
||||
mainframe->m_topbar->show_publish_button(publish_identifier == 0 ? false : true);
|
||||
}
|
||||
#else
|
||||
mainframe->show_publish_button(publish_identifier == 0 ? false : true);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_is_recreating_gui = false;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "recreate_GUI exit";
|
||||
|
|
@ -3436,22 +3623,6 @@ std::string GUI_App::handle_web_request(std::string cmd)
|
|||
{
|
||||
try {
|
||||
//BBS use nlohmann json format
|
||||
json j = json::parse(cmd);
|
||||
|
||||
std::string web_cmd = j["command"].get<std::string>();
|
||||
|
||||
if (web_cmd == "request_model_download") {
|
||||
std::string download_url = "";
|
||||
if (j["data"].contains("download_url"))
|
||||
download_url = j["data"]["download_url"].get<std::string>();
|
||||
|
||||
std::string filename = "";
|
||||
if (j["data"].contains("filename"))
|
||||
download_url = j["data"]["filename"].get<std::string>();
|
||||
|
||||
this->request_model_download(download_url, filename);
|
||||
}
|
||||
|
||||
std::stringstream ss(cmd), oss;
|
||||
pt::ptree root, response;
|
||||
pt::read_json(ss, root);
|
||||
|
|
@ -3631,12 +3802,10 @@ void GUI_App::handle_script_message(std::string msg)
|
|||
}
|
||||
}
|
||||
|
||||
void GUI_App::request_model_download(std::string url, std::string filename)
|
||||
void GUI_App::request_model_download(std::string url)
|
||||
{
|
||||
if (!check_login()) return;
|
||||
|
||||
if (plater_) {
|
||||
plater_->request_model_download();
|
||||
plater_->request_model_download(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3771,15 +3940,15 @@ void GUI_App::on_user_login_handle(wxCommandEvent &evt)
|
|||
wxQueueEvent(this, evt);
|
||||
});
|
||||
|
||||
// if (app_config->get("sync_user_preset") == "true") {
|
||||
enable_user_preset_folder(true);
|
||||
// } else {
|
||||
// enable_user_preset_folder(false);
|
||||
// }
|
||||
|
||||
|
||||
if (online_login)
|
||||
GUI::wxGetApp().mainframe->show_sync_dialog();
|
||||
|
||||
else if (app_config->get("sync_user_preset") == "true") {
|
||||
enable_user_preset_folder(true);
|
||||
} else {
|
||||
enable_user_preset_folder(false);
|
||||
}
|
||||
//show publish button
|
||||
if (m_agent->is_user_login() && mainframe) {
|
||||
int identifier;
|
||||
|
|
@ -3796,12 +3965,30 @@ void GUI_App::on_user_login_handle(wxCommandEvent &evt)
|
|||
}
|
||||
}
|
||||
|
||||
void GUI_App::check_track_enable()
|
||||
{
|
||||
if (app_config && app_config->get("firstguide", "privacyuse") == "true") {
|
||||
//enable track event
|
||||
json header_json;
|
||||
header_json["ver"] = SLIC3R_VERSION;
|
||||
wxString os_desc = wxGetOsDescription();
|
||||
int major = 0, minor = 0, micro = 0;
|
||||
header_json["os"] = std::string(os_desc.ToUTF8());
|
||||
header_json["name"] = std::string(SLIC3R_APP_NAME);
|
||||
if (m_agent) {
|
||||
m_agent->track_header(header_json.dump());
|
||||
m_agent->track_enable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_App::on_user_login(wxCommandEvent &evt)
|
||||
{
|
||||
if (!m_agent) { return; }
|
||||
int online_login = evt.GetInt();
|
||||
// check privacy before handle
|
||||
check_privacy_version(online_login);
|
||||
check_track_enable();
|
||||
}
|
||||
|
||||
bool GUI_App::is_studio_active()
|
||||
|
|
@ -4295,6 +4482,9 @@ void GUI_App::start_sync_user_preset(bool load_immediately, bool with_progress_d
|
|||
{
|
||||
if (!m_agent || !m_agent->is_user_login()) return;
|
||||
|
||||
if (load_immediately)
|
||||
remove_user_presets();
|
||||
|
||||
enable_user_preset_folder(true);
|
||||
|
||||
// has already start sync
|
||||
|
|
@ -4411,6 +4601,9 @@ void GUI_App::stop_sync_user_preset()
|
|||
remove_user_presets();
|
||||
enable_user_preset_folder(false);
|
||||
|
||||
preset_bundle->load_user_presets(DEFAULT_USER_FOLDER_NAME, ForwardCompatibilitySubstitutionRule::Enable);
|
||||
mainframe->update_side_preset_ui();
|
||||
|
||||
if (!enable_sync)
|
||||
return;
|
||||
|
||||
|
|
@ -4519,6 +4712,7 @@ int GUI_App::GetSingleChoiceIndex(const wxString& message,
|
|||
{
|
||||
#ifdef _WIN32
|
||||
wxSingleChoiceDialog dialog(nullptr, message, caption, choices);
|
||||
dialog.SetBackgroundColour(*wxWHITE);
|
||||
wxGetApp().UpdateDlgDarkUI(&dialog);
|
||||
|
||||
dialog.SetSelection(initialSelection);
|
||||
|
|
@ -4733,7 +4927,8 @@ bool GUI_App::load_language(wxString language, bool initial)
|
|||
wxLANGUAGE_SWEDISH,
|
||||
wxLANGUAGE_DUTCH,
|
||||
wxLANGUAGE_HUNGARIAN,
|
||||
wxLANGUAGE_JAPANESE
|
||||
wxLANGUAGE_JAPANESE,
|
||||
wxLANGUAGE_ITALIAN
|
||||
};
|
||||
std::string cur_language = app_config->get("language");
|
||||
if (cur_language != "") {
|
||||
|
|
@ -4800,6 +4995,11 @@ Tab* GUI_App::get_model_tab(bool part)
|
|||
return model_tabs_list[part ? 1 : 0];
|
||||
}
|
||||
|
||||
Tab* GUI_App::get_layer_tab()
|
||||
{
|
||||
return model_tabs_list[2];
|
||||
}
|
||||
|
||||
ConfigOptionMode GUI_App::get_mode()
|
||||
{
|
||||
if (!app_config->has("user_mode"))
|
||||
|
|
@ -5142,6 +5342,8 @@ bool GUI_App::check_and_save_current_preset_changes(const wxString& caption, con
|
|||
int act_buttons = UnsavedChangesDialog::ActionButtons::SAVE;
|
||||
if (dont_save_insted_of_discard)
|
||||
act_buttons |= UnsavedChangesDialog::ActionButtons::DONT_SAVE;
|
||||
if (remember_choice)
|
||||
act_buttons |= UnsavedChangesDialog::ActionButtons::REMEMBER_CHOISE;
|
||||
UnsavedChangesDialog dlg(caption, header, "", act_buttons);
|
||||
if (dlg.ShowModal() == wxID_CANCEL)
|
||||
return false;
|
||||
|
|
@ -5390,6 +5592,33 @@ void GUI_App::OSXStoreOpenFiles(const wxArrayString &fileNames)
|
|||
}*/
|
||||
wxApp::OSXStoreOpenFiles(fileNames);
|
||||
}
|
||||
|
||||
void GUI_App::MacOpenURL(const wxString& url)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "get mac url " << url;
|
||||
|
||||
if (!url.empty() && boost::starts_with(url, "bambustudioopen://")) {
|
||||
auto input_str_arr = split_str(url.ToStdString(), "bambustudioopen://");
|
||||
|
||||
std::string download_origin_url;
|
||||
for (auto input_str : input_str_arr) {
|
||||
if (!input_str.empty()) download_origin_url = input_str;
|
||||
}
|
||||
|
||||
std::string download_file_url = url_decode(download_origin_url);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << download_file_url;
|
||||
if (!download_file_url.empty() && (boost::starts_with(download_file_url, "http://") || boost::starts_with(download_file_url, "https://"))) {
|
||||
|
||||
if (m_post_initialized) {
|
||||
request_model_download(download_file_url);
|
||||
}
|
||||
else {
|
||||
m_download_file_url = download_file_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wxWidgets override to get an event on open files.
|
||||
void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
|
||||
{
|
||||
|
|
@ -5455,6 +5684,7 @@ void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
|
|||
start_new_gcodeviewer(&filename);*/
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __APPLE */
|
||||
|
||||
Sidebar& GUI_App::sidebar()
|
||||
|
|
@ -5472,6 +5702,11 @@ ObjectList* GUI_App::obj_list()
|
|||
return sidebar().obj_list();
|
||||
}
|
||||
|
||||
ObjectLayers* GUI_App::obj_layers()
|
||||
{
|
||||
return sidebar().obj_layers();
|
||||
}
|
||||
|
||||
Plater* GUI_App::plater()
|
||||
{
|
||||
return plater_;
|
||||
|
|
@ -5509,45 +5744,85 @@ void GUI_App::load_url(wxString url)
|
|||
|
||||
void GUI_App::open_mall_page_dialog()
|
||||
{
|
||||
std::string url;
|
||||
std::string host_url;
|
||||
std::string model_url;
|
||||
std::string link_url;
|
||||
|
||||
int result = -1;
|
||||
|
||||
//model api url
|
||||
host_url = get_model_http_url(app_config->get_country_code());
|
||||
|
||||
//model url
|
||||
|
||||
wxString language_code = this->current_language_code().BeforeFirst('_');
|
||||
model_url = language_code.ToStdString();
|
||||
|
||||
if (getAgent() && mainframe) {
|
||||
getAgent()->get_model_mall_home_url(&url);
|
||||
|
||||
if (!m_mall_home_dialog) {
|
||||
m_mall_home_dialog = new ModelMallDialog();
|
||||
m_mall_home_dialog->go_to_mall(url);
|
||||
}
|
||||
else {
|
||||
if (m_mall_home_dialog->IsIconized())
|
||||
m_mall_home_dialog->Iconize(false);
|
||||
//login already
|
||||
if (getAgent()->is_user_login()) {
|
||||
std::string ticket;
|
||||
result = getAgent()->request_bind_ticket(&ticket);
|
||||
|
||||
//m_mall_home_dialog->go_to_mall(url);
|
||||
if(result == 0){
|
||||
link_url = host_url + "api/sign-in/ticket?to=" + host_url + url_encode(model_url) + "&ticket=" + ticket;
|
||||
}
|
||||
}
|
||||
m_mall_home_dialog->Raise();
|
||||
m_mall_home_dialog->Show();
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
link_url = host_url + model_url;
|
||||
}
|
||||
|
||||
wxLaunchDefaultBrowser(link_url);
|
||||
}
|
||||
|
||||
void GUI_App::open_publish_page_dialog()
|
||||
{
|
||||
std::string url;
|
||||
std::string host_url;
|
||||
std::string model_url;
|
||||
std::string link_url;
|
||||
|
||||
int result = -1;
|
||||
|
||||
//model api url
|
||||
host_url = get_model_http_url(app_config->get_country_code());
|
||||
|
||||
//publish url
|
||||
wxString language_code = this->current_language_code().BeforeFirst('_');
|
||||
model_url += (language_code.ToStdString() + "/my/models/publish");
|
||||
|
||||
if (getAgent() && mainframe) {
|
||||
getAgent()->get_model_publish_url(&url);
|
||||
|
||||
if (!m_mall_publish_dialog) {
|
||||
m_mall_publish_dialog = new ModelMallDialog();
|
||||
m_mall_publish_dialog->go_to_mall(url);
|
||||
}
|
||||
else {
|
||||
if (m_mall_publish_dialog->IsIconized())
|
||||
m_mall_publish_dialog->Iconize(false);
|
||||
//login already
|
||||
if (getAgent()->is_user_login()) {
|
||||
std::string ticket;
|
||||
result = getAgent()->request_bind_ticket(&ticket);
|
||||
|
||||
//m_mall_publish_dialog->go_to_publish(url);
|
||||
if (result == 0) {
|
||||
link_url = host_url + "api/sign-in/ticket?to=" + host_url + url_encode(model_url) + "&ticket=" + ticket;
|
||||
}
|
||||
}
|
||||
m_mall_publish_dialog->Raise();
|
||||
m_mall_publish_dialog->Show();
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
link_url = host_url + model_url;
|
||||
}
|
||||
|
||||
wxLaunchDefaultBrowser(link_url);
|
||||
}
|
||||
|
||||
char GUI_App::from_hex(char ch) {
|
||||
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
|
||||
}
|
||||
|
||||
std::string GUI_App::url_decode(std::string value) {
|
||||
return Http::url_decode(value);
|
||||
}
|
||||
|
||||
std::string GUI_App::url_encode(std::string value) {
|
||||
return Http::url_encode(value);
|
||||
}
|
||||
|
||||
void GUI_App::remove_mall_system_dialog()
|
||||
|
|
@ -5556,12 +5831,6 @@ void GUI_App::remove_mall_system_dialog()
|
|||
m_mall_publish_dialog->Destroy();
|
||||
delete m_mall_publish_dialog;
|
||||
}
|
||||
|
||||
|
||||
if (m_mall_home_dialog != nullptr) {
|
||||
m_mall_home_dialog->Destroy();
|
||||
delete m_mall_home_dialog;
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_App::run_script(wxString js)
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ class MainFrame;
|
|||
class Sidebar;
|
||||
class ObjectSettings;
|
||||
class ObjectList;
|
||||
class ObjectLayers;
|
||||
class Plater;
|
||||
class ParamsPanel;
|
||||
class NotificationManager;
|
||||
|
|
@ -227,6 +228,8 @@ private:
|
|||
bool m_opengl_initialized{ false };
|
||||
#endif
|
||||
|
||||
//import model from mall
|
||||
std::string m_download_file_url;
|
||||
|
||||
//#ifdef _WIN32
|
||||
wxColour m_color_label_modified;
|
||||
|
|
@ -408,7 +411,7 @@ private:
|
|||
int request_user_unbind(std::string dev_id);
|
||||
std::string handle_web_request(std::string cmd);
|
||||
void handle_script_message(std::string msg);
|
||||
void request_model_download(std::string url, std::string filename);
|
||||
void request_model_download(std::string url);
|
||||
void download_project(std::string project_id);
|
||||
void request_project_download(std::string project_id);
|
||||
void request_open_project(std::string project_id);
|
||||
|
|
@ -449,6 +452,7 @@ private:
|
|||
void on_check_privacy_update(wxCommandEvent &evt);
|
||||
bool check_privacy_update();
|
||||
void check_privacy_version(int online_login = 0);
|
||||
void check_track_enable();
|
||||
|
||||
static bool catch_error(std::function<void()> cb, const std::string& err);
|
||||
|
||||
|
|
@ -460,6 +464,7 @@ private:
|
|||
|
||||
Tab* get_tab(Preset::Type type);
|
||||
Tab* get_model_tab(bool part = false);
|
||||
Tab* get_layer_tab();
|
||||
ConfigOptionMode get_mode();
|
||||
void save_mode(const /*ConfigOptionMode*/int mode) ;
|
||||
void update_mode();
|
||||
|
|
@ -501,11 +506,13 @@ private:
|
|||
void OSXStoreOpenFiles(const wxArrayString &files);
|
||||
// wxWidgets override to get an event on open files.
|
||||
void MacOpenFiles(const wxArrayString &fileNames) override;
|
||||
void MacOpenURL(const wxString& url) override;
|
||||
#endif /* __APPLE */
|
||||
|
||||
Sidebar& sidebar();
|
||||
ObjectSettings* obj_settings();
|
||||
ObjectList* obj_list();
|
||||
ObjectLayers* obj_layers();
|
||||
Plater* plater();
|
||||
const Plater* plater() const;
|
||||
ParamsPanel* params_panel();
|
||||
|
|
@ -516,7 +523,6 @@ private:
|
|||
|
||||
std::string m_mall_model_download_url;
|
||||
std::string m_mall_model_download_name;
|
||||
ModelMallDialog* m_mall_home_dialog{ nullptr };
|
||||
ModelMallDialog* m_mall_publish_dialog{ nullptr };
|
||||
|
||||
void set_download_model_url(std::string url) {m_mall_model_download_url = url;}
|
||||
|
|
@ -532,6 +538,10 @@ private:
|
|||
bool is_adding_script_handler() { return m_adding_script_handler; }
|
||||
void set_adding_script_handler(bool status) { m_adding_script_handler = status; }
|
||||
|
||||
char from_hex(char ch);
|
||||
std::string url_encode(std::string value);
|
||||
std::string url_decode(std::string value);
|
||||
|
||||
// Parameters extracted from the command line to be passed to GUI after initialization.
|
||||
GUI_InitParams* init_params { nullptr };
|
||||
|
||||
|
|
@ -593,6 +603,7 @@ private:
|
|||
int download_plugin(std::string name, std::string package_name, InstallProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr);
|
||||
int install_plugin(std::string name, std::string package_name, InstallProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr);
|
||||
std::string get_http_url(std::string country_code);
|
||||
std::string get_model_http_url(std::string country_code);
|
||||
bool is_compatibility_version();
|
||||
bool check_networking_version();
|
||||
void cancel_networking_install();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "slic3r/Utils/FixModelByWin10.hpp"
|
||||
#include "ParamsPanel.hpp"
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
|
|
@ -200,7 +201,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::get_all_v
|
|||
}
|
||||
|
||||
|
||||
SettingsFactory::Bundle SettingsFactory::get_bundle(const DynamicPrintConfig* config, bool is_object_settings)
|
||||
SettingsFactory::Bundle SettingsFactory::get_bundle(const DynamicPrintConfig* config, bool is_object_settings, bool is_layer_settings/* = false*/)
|
||||
{
|
||||
auto opt_keys = config->keys();
|
||||
if (opt_keys.empty())
|
||||
|
|
@ -208,6 +209,8 @@ SettingsFactory::Bundle SettingsFactory::get_bundle(const DynamicPrintConfig* co
|
|||
|
||||
// update options list according to print technology
|
||||
auto full_current_opts = get_options(!is_object_settings);
|
||||
if (is_layer_settings)
|
||||
full_current_opts.push_back("layer_height");
|
||||
for (int i = opt_keys.size() - 1; i >= 0; --i)
|
||||
if (find(full_current_opts.begin(), full_current_opts.end(), opt_keys[i]) == full_current_opts.end())
|
||||
opt_keys.erase(opt_keys.begin() + i);
|
||||
|
|
@ -448,7 +451,7 @@ void MenuFactory::append_menu_item_set_visible(wxMenu* menu)
|
|||
void MenuFactory::append_menu_item_delete(wxMenu* menu)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Delete the selected object"),
|
||||
append_menu_item(menu, wxID_ANY, _L("Delete") + "\t" + _L("Del"), _L("Delete the selected object"),
|
||||
[](wxCommandEvent&) { plater()->remove_selected(); }, "menu_delete", nullptr,
|
||||
[]() { return plater()->can_delete(); }, m_parent);
|
||||
#else
|
||||
|
|
@ -534,6 +537,15 @@ void MenuFactory::append_menu_items_add_volume(wxMenu* menu)
|
|||
append_submenu(menu, sub_menu, wxID_ANY, _(item.first), "", item.second,
|
||||
[]() { return obj_list()->is_instance_or_object_selected(); }, m_parent);
|
||||
}
|
||||
|
||||
append_menu_item_layers_editing(menu);
|
||||
}
|
||||
|
||||
wxMenuItem* MenuFactory::append_menu_item_layers_editing(wxMenu* menu)
|
||||
{
|
||||
return append_menu_item(menu, wxID_ANY, _L("Height range Modifier"), "",
|
||||
[](wxCommandEvent&) { obj_list()->layers_editing(); wxGetApp().params_panel()->switch_to_object(); }, "", menu,
|
||||
[]() { return obj_list()->is_instance_or_object_selected(); }, m_parent);
|
||||
}
|
||||
|
||||
wxMenuItem* MenuFactory::append_menu_item_settings(wxMenu* menu_)
|
||||
|
|
@ -577,7 +589,7 @@ wxMenuItem* MenuFactory::append_menu_item_settings(wxMenu* menu_)
|
|||
|
||||
if (printer_technology() == ptFFF ||
|
||||
(menu->GetMenuItems().size() > 0 && !menu->GetMenuItems().back()->IsSeparator()))
|
||||
menu->SetFirstSeparator();
|
||||
;// menu->SetFirstSeparator();
|
||||
|
||||
// detect itemm for adding of the setting
|
||||
ObjectList* object_list = obj_list();
|
||||
|
|
@ -601,7 +613,7 @@ wxMenuItem* MenuFactory::append_menu_item_settings(wxMenu* menu_)
|
|||
// BBS remvoe freq setting popupmenu
|
||||
// create_freq_settings_popupmenu(menu, is_object_settings, item);
|
||||
|
||||
menu->SetSecondSeparator();
|
||||
//menu->SetSecondSeparator();
|
||||
|
||||
// Add full settings list
|
||||
auto menu_item = new wxMenuItem(menu, wxID_ANY, menu_name);
|
||||
|
|
@ -942,6 +954,20 @@ void MenuFactory::append_menu_items_mirror(wxMenu* menu)
|
|||
[]() { return plater()->can_mirror(); }, m_parent);
|
||||
}
|
||||
|
||||
void MenuFactory::append_menu_item_invalidate_cut_info(wxMenu *menu)
|
||||
{
|
||||
const wxString menu_name = _L("Invalidate cut info");
|
||||
|
||||
auto menu_item_id = menu->FindItem(menu_name);
|
||||
if (menu_item_id != wxNOT_FOUND)
|
||||
// Delete old menu item if selected object isn't cut
|
||||
menu->Destroy(menu_item_id);
|
||||
|
||||
if (obj_list()->has_selected_cut_object())
|
||||
append_menu_item(menu, wxID_ANY, menu_name, "", [](wxCommandEvent &) { obj_list()->invalidate_cut_info_for_selection(); },
|
||||
"", menu, []() { return true; }, m_parent);
|
||||
}
|
||||
|
||||
MenuFactory::MenuFactory()
|
||||
{
|
||||
for (int i = 0; i < mtCount; i++) {
|
||||
|
|
@ -1199,11 +1225,11 @@ void MenuFactory::create_plate_menu()
|
|||
|
||||
// delete current plate
|
||||
#ifdef __WINDOWS__
|
||||
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Remove the selected plate"),
|
||||
append_menu_item(menu, wxID_ANY, _L("Delete Plate"), _L("Remove the selected plate"),
|
||||
[](wxCommandEvent&) { plater()->delete_plate(); }, "menu_delete", nullptr,
|
||||
[]() { return plater()->can_delete_plate(); }, m_parent);
|
||||
#else
|
||||
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tBackSpace", _L("Remove the selected plate"),
|
||||
append_menu_item(menu, wxID_ANY, _L("Delete Plate"), _L("Remove the selected plate"),
|
||||
[](wxCommandEvent&) { plater()->delete_plate(); }, "", nullptr,
|
||||
[]() { return plater()->can_delete_plate(); }, m_parent);
|
||||
#endif
|
||||
|
|
@ -1263,6 +1289,7 @@ wxMenu* MenuFactory::object_menu()
|
|||
append_menu_item_change_filament(&m_object_menu);
|
||||
append_menu_items_convert_unit(&m_object_menu);
|
||||
append_menu_items_flush_options(&m_object_menu);
|
||||
append_menu_item_invalidate_cut_info(&m_object_menu);
|
||||
return &m_object_menu;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ struct SettingsFactory
|
|||
static std::map<std::string, std::vector<SimpleSettingData>> PART_CATEGORY_SETTINGS;
|
||||
|
||||
static wxBitmap get_category_bitmap(const std::string& category_name, bool menu_bmp = true);
|
||||
static Bundle get_bundle(const DynamicPrintConfig* config, bool is_object_settings);
|
||||
static Bundle get_bundle(const DynamicPrintConfig* config, bool is_object_settings, bool is_layer_settings = false);
|
||||
static std::vector<std::string> get_options(bool is_part);
|
||||
//BBS: add api to get options for catogary
|
||||
static std::vector<SimpleSettingData> get_visible_options(const std::string& category, const bool is_part);
|
||||
|
|
@ -115,6 +115,7 @@ private:
|
|||
|
||||
wxMenu* append_submenu_add_generic(wxMenu* menu, ModelVolumeType type);
|
||||
void append_menu_items_add_volume(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_layers_editing(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_settings(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_change_type(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu);
|
||||
|
|
@ -136,6 +137,8 @@ private:
|
|||
void append_menu_item_merge_to_single_object(wxMenu* menu);
|
||||
void append_menu_item_merge_parts_to_single_part(wxMenu *menu);
|
||||
void append_menu_items_mirror(wxMenu *menu);
|
||||
void append_menu_item_invalidate_cut_info(wxMenu *menu);
|
||||
|
||||
//void append_menu_items_instance_manipulation(wxMenu *menu);
|
||||
//void update_menu_items_instance_manipulation(MenuType type);
|
||||
//BBS add bbl menu item
|
||||
|
|
|
|||
|
|
@ -22,24 +22,15 @@ namespace GUI
|
|||
ObjectLayers::ObjectLayers(wxWindow* parent) :
|
||||
OG_Settings(parent, true)
|
||||
{
|
||||
m_grid_sizer = new wxFlexGridSizer(3, 5, wxGetApp().em_unit()); // "Min Z", "Max Z", "Layer height" & buttons sizer
|
||||
m_grid_sizer = new wxFlexGridSizer(3, 0, wxGetApp().em_unit()); // "Min Z", "Max Z", "Layer height" & buttons sizer
|
||||
m_grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
|
||||
|
||||
// Legend for object layers
|
||||
for (const std::string col : { L("From height"), L("To height"), L("Layer height") }) {
|
||||
auto temp = new wxStaticText(m_parent, wxID_ANY, _(col), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_MIDDLE);
|
||||
temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
temp->SetFont(wxGetApp().bold_font());
|
||||
|
||||
m_grid_sizer->Add(temp);
|
||||
}
|
||||
|
||||
m_og->activate();
|
||||
m_og->sizer->Clear(true);
|
||||
m_og->sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX ? 0 : 5);
|
||||
m_og->sizer->Add(m_grid_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, wxOSX ? 0 : 5);
|
||||
|
||||
m_bmp_delete = ScalableBitmap(parent, "remove_copies"/*"cross"*/);
|
||||
m_bmp_add = ScalableBitmap(parent, "add_copies");
|
||||
m_bmp_delete = ScalableBitmap(parent, "delete_filament"/*"cross"*/);
|
||||
m_bmp_add = ScalableBitmap(parent, "add_filament");
|
||||
}
|
||||
|
||||
void ObjectLayers::select_editor(LayerRangeEditor* editor, const bool is_last_edited_range)
|
||||
|
|
@ -80,6 +71,12 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
|
|||
m_selection_type = type;
|
||||
};
|
||||
|
||||
// Add text
|
||||
auto head_text = new wxStaticText(m_parent, wxID_ANY, _L("Height Range"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
head_text->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
head_text->SetFont(wxGetApp().normal_font());
|
||||
m_grid_sizer->Add(head_text, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, wxGetApp().em_unit());
|
||||
|
||||
// Add control for the "Min Z"
|
||||
|
||||
auto editor = new LayerRangeEditor(this, double_to_string(range.first), etMinZ, set_focus_data,
|
||||
|
|
@ -103,7 +100,15 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
|
|||
});
|
||||
|
||||
select_editor(editor, is_last_edited_range);
|
||||
m_grid_sizer->Add(editor);
|
||||
|
||||
auto sizer1 = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer1->Add(editor);
|
||||
auto middle_text = new wxStaticText(m_parent, wxID_ANY, _L("to"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
middle_text->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
middle_text->SetFont(wxGetApp().normal_font());
|
||||
sizer1->Add(middle_text, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, wxGetApp().em_unit());
|
||||
|
||||
m_grid_sizer->Add(sizer1);
|
||||
|
||||
// Add control for the "Max Z"
|
||||
|
||||
|
|
@ -127,29 +132,38 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
|
|||
});
|
||||
|
||||
select_editor(editor, is_last_edited_range);
|
||||
m_grid_sizer->Add(editor);
|
||||
|
||||
auto sizer2 = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer2->Add(editor);
|
||||
auto unit_text = new wxStaticText(m_parent, wxID_ANY, _L("mm"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
unit_text->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
unit_text->SetFont(wxGetApp().normal_font());
|
||||
sizer2->Add(unit_text, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, wxGetApp().em_unit());
|
||||
|
||||
m_grid_sizer->Add(sizer2);
|
||||
|
||||
// BBS
|
||||
// Add control for the "Layer height"
|
||||
|
||||
editor = new LayerRangeEditor(this, double_to_string(m_object->layer_config_ranges[range].option("layer_height")->getFloat()), etLayerHeight, set_focus_data,
|
||||
[range](coordf_t layer_height, bool, bool)
|
||||
{
|
||||
return wxGetApp().obj_list()->edit_layer_range(range, layer_height);
|
||||
});
|
||||
//editor = new LayerRangeEditor(this, double_to_string(m_object->layer_config_ranges[range].option("layer_height")->getFloat()), etLayerHeight, set_focus_data,
|
||||
// [range](coordf_t layer_height, bool, bool)
|
||||
//{
|
||||
// return wxGetApp().obj_list()->edit_layer_range(range, layer_height);
|
||||
//});
|
||||
|
||||
select_editor(editor, is_last_edited_range);
|
||||
//select_editor(editor, is_last_edited_range);
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(editor);
|
||||
//auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
//sizer->Add(editor);
|
||||
|
||||
auto temp = new wxStaticText(m_parent, wxID_ANY, _L("mm"));
|
||||
temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
temp->SetFont(wxGetApp().normal_font());
|
||||
sizer->Add(temp, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, wxGetApp().em_unit());
|
||||
//auto temp = new wxStaticText(m_parent, wxID_ANY, _L("mm"));
|
||||
//temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
//temp->SetFont(wxGetApp().normal_font());
|
||||
//sizer->Add(temp, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, wxGetApp().em_unit());
|
||||
|
||||
m_grid_sizer->Add(sizer);
|
||||
//m_grid_sizer->Add(sizer);
|
||||
|
||||
return sizer;
|
||||
return sizer2;
|
||||
}
|
||||
|
||||
void ObjectLayers::create_layers_list()
|
||||
|
|
@ -157,9 +171,11 @@ void ObjectLayers::create_layers_list()
|
|||
for (const auto &layer : m_object->layer_config_ranges) {
|
||||
const t_layer_height_range& range = layer.first;
|
||||
auto del_btn = new PlusMinusButton(m_parent, m_bmp_delete, range);
|
||||
del_btn->SetBackgroundColour(m_parent->GetBackgroundColour());
|
||||
del_btn->SetToolTip(_L("Remove height range"));
|
||||
|
||||
auto add_btn = new PlusMinusButton(m_parent, m_bmp_add, range);
|
||||
add_btn->SetBackgroundColour(m_parent->GetBackgroundColour());
|
||||
wxString tooltip = wxGetApp().obj_list()->can_add_new_range_after_current(range);
|
||||
add_btn->SetToolTip(tooltip.IsEmpty() ? _L("Add height range") : tooltip);
|
||||
add_btn->Enable(tooltip.IsEmpty());
|
||||
|
|
@ -195,18 +211,8 @@ void ObjectLayers::update_layers_list()
|
|||
m_object = objects_ctrl->object(obj_idx);
|
||||
if (!m_object || m_object->layer_config_ranges.empty()) return;
|
||||
|
||||
// Delete all controls from options group except of the legends
|
||||
|
||||
const int cols = m_grid_sizer->GetEffectiveColsCount();
|
||||
const int rows = m_grid_sizer->GetEffectiveRowsCount();
|
||||
for (int idx = cols*rows-1; idx >= cols; idx--) {
|
||||
wxSizerItem* t = m_grid_sizer->GetItem(idx);
|
||||
if (t->IsSizer())
|
||||
t->GetSizer()->Clear(true);
|
||||
else
|
||||
t->DeleteWindows();
|
||||
m_grid_sizer->Remove(idx);
|
||||
}
|
||||
// Delete all controls from options group
|
||||
m_grid_sizer->Clear(true);
|
||||
|
||||
// Add new control according to the selected item
|
||||
|
||||
|
|
@ -283,7 +289,7 @@ void ObjectLayers::sys_color_changed()
|
|||
if (item->IsSizer()) {// case when we have editor with buttons
|
||||
for (size_t btn : {2, 3}) { // del_btn, add_btn
|
||||
wxSizerItem* b_item = item->GetSizer()->GetItem(btn);
|
||||
if (b_item->IsWindow()) {
|
||||
if (b_item && b_item->IsWindow()) {
|
||||
auto button = dynamic_cast<PlusMinusButton*>(b_item->GetWindow());
|
||||
if (button != nullptr)
|
||||
button->msw_rescale();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -225,6 +225,7 @@ public:
|
|||
// BBS
|
||||
void set_color_paint_hidden(const bool hide) const;
|
||||
void set_support_paint_hidden(const bool hide) const;
|
||||
void set_sinking_hidden(const bool hide) const;
|
||||
|
||||
// update extruder in current config
|
||||
void update_filament_in_config(const wxDataViewItem& item);
|
||||
|
|
@ -285,12 +286,13 @@ public:
|
|||
// BBS
|
||||
void switch_to_object_process();
|
||||
int load_mesh_part(const TriangleMesh &mesh, const wxString &name, const TextInfo &text_info, bool is_temp);
|
||||
void del_object(const int obj_idx, bool refresh_immediately = true);
|
||||
bool del_object(const int obj_idx, bool refresh_immediately = true);
|
||||
void del_subobject_item(wxDataViewItem& item);
|
||||
void del_settings_from_config(const wxDataViewItem& parent_item);
|
||||
void del_instances_from_object(const int obj_idx);
|
||||
void del_layer_from_object(const int obj_idx, const t_layer_height_range& layer_range);
|
||||
void del_layers_from_object(const int obj_idx);
|
||||
bool del_from_cut_object(bool is_connector, bool is_model_part = false, bool is_negative_volume = false);
|
||||
bool del_subobject_from_object(const int obj_idx, const int idx, const int type);
|
||||
void del_info_item(const int obj_idx, InfoItemType type);
|
||||
void split();
|
||||
|
|
@ -309,6 +311,12 @@ public:
|
|||
bool can_merge_to_multipart_object() const;
|
||||
bool can_merge_to_single_object() const;
|
||||
|
||||
bool has_selected_cut_object() const;
|
||||
void invalidate_cut_info_for_selection();
|
||||
void invalidate_cut_info_for_object(int obj_idx);
|
||||
void delete_all_connectors_for_selection();
|
||||
void delete_all_connectors_for_object(int obj_idx);
|
||||
|
||||
wxPoint get_mouse_position_in_control() const { return wxGetMousePosition() - this->GetScreenPosition(); }
|
||||
int get_selected_obj_idx() const;
|
||||
ModelConfig& get_item_config(const wxDataViewItem& item) const;
|
||||
|
|
@ -318,6 +326,9 @@ public:
|
|||
|
||||
// Add object to the list
|
||||
void add_object_to_list(size_t obj_idx, bool call_selection_changed = true, bool notify_partplate = true);
|
||||
// Add object's volumes to the list
|
||||
// Return selected items, if add_to_selection is defined
|
||||
wxDataViewItemArray add_volumes_to_object_in_list(size_t obj_idx, std::function<bool(const ModelVolume *)> add_to_selection = nullptr);
|
||||
// Delete object from the list
|
||||
void delete_object_from_list();
|
||||
void delete_object_from_list(const size_t obj_idx);
|
||||
|
|
@ -325,6 +336,7 @@ public:
|
|||
void delete_instance_from_list(const size_t obj_idx, const size_t inst_idx);
|
||||
void delete_from_model_and_list(const ItemType type, const int obj_idx, const int sub_obj_idx);
|
||||
void delete_from_model_and_list(const std::vector<ItemForDelete>& items_for_delete);
|
||||
void update_lock_icons_for_model();
|
||||
// Delete all objects from the list
|
||||
void delete_all_objects_from_list();
|
||||
// Increase instances count
|
||||
|
|
@ -367,6 +379,8 @@ public:
|
|||
void init();
|
||||
bool multiple_selection() const ;
|
||||
bool is_selected(const ItemType type) const;
|
||||
bool is_connectors_item_selected() const;
|
||||
bool is_connectors_item_selected(const wxDataViewItemArray &sels) const;
|
||||
int get_selected_layers_range_idx() const;
|
||||
void set_selected_layers_range_idx(const int range_idx) { m_selected_layers_range_idx = range_idx; }
|
||||
void set_selection_mode(SELECTION_MODE mode) { m_selection_mode = mode; }
|
||||
|
|
@ -384,6 +398,9 @@ public:
|
|||
bool check_last_selection(wxString& msg_str);
|
||||
// correct current selections to avoid of the possible conflicts
|
||||
void fix_multiselection_conflicts();
|
||||
// correct selection in respect to the cut_id if any exists
|
||||
void fix_cut_selection();
|
||||
bool fix_cut_selection(wxDataViewItemArray &sels);
|
||||
|
||||
ModelVolume* get_selected_model_volume();
|
||||
void change_part_type();
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ namespace GUI
|
|||
OG_Settings::OG_Settings(wxWindow* parent, const bool staticbox) :
|
||||
m_parent(parent)
|
||||
{
|
||||
wxString title = staticbox ? " " : ""; // temporary workaround - #ys_FIXME
|
||||
//BBS
|
||||
wxString title = "";
|
||||
//wxString title = staticbox ? " " : ""; // temporary workaround - #ys_FIXME
|
||||
m_og = std::make_shared<ConfigOptionsGroup>(parent, title);
|
||||
}
|
||||
|
||||
|
|
@ -106,13 +108,14 @@ bool ObjectSettings::update_settings_list()
|
|||
auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line
|
||||
|
||||
auto btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete);
|
||||
btn->SetBackgroundColour(parent->GetBackgroundColour());
|
||||
btn->SetToolTip(_(L("Remove parameter")));
|
||||
|
||||
btn->SetBitmapFocus(m_bmp_delete_focus.bmp());
|
||||
btn->SetBitmapHover(m_bmp_delete_focus.bmp());
|
||||
|
||||
btn->Bind(wxEVT_BUTTON, [opt_key, config, this](wxEvent &event) {
|
||||
wxGetApp().plater()->take_snapshot(from_u8(boost::format(("Delete Option %s") % opt_key).str()));
|
||||
wxGetApp().plater()->take_snapshot(from_u8((boost::format("Delete Option %s") % opt_key).str()).ToStdString());
|
||||
config->erase(opt_key);
|
||||
wxGetApp().obj_list()->changed_object();
|
||||
wxTheApp->CallAfter([this]() {
|
||||
|
|
@ -159,7 +162,7 @@ bool ObjectSettings::update_settings_list()
|
|||
for (auto& opt : cat.second)
|
||||
optgroup->get_field(opt)->m_on_change = [optgroup](const std::string& opt_id, const boost::any& value) {
|
||||
// first of all take a snapshot and then change value in configuration
|
||||
wxGetApp().plater()->take_snapshot(from_u8((boost::format("Change Option %s")% opt_id).str()));
|
||||
wxGetApp().plater()->take_snapshot(from_u8((boost::format("Change Option %s")% opt_id).str()).ToStdString());
|
||||
optgroup->on_change_OG(opt_id, value);
|
||||
};
|
||||
|
||||
|
|
@ -183,7 +186,6 @@ bool ObjectSettings::update_settings_list()
|
|||
}
|
||||
|
||||
#else
|
||||
|
||||
bool ObjectSettings::update_settings_list()
|
||||
{
|
||||
if (!wxGetApp().is_editor())
|
||||
|
|
@ -198,51 +200,74 @@ bool ObjectSettings::update_settings_list()
|
|||
objects_ctrl->GetSelections(items);
|
||||
|
||||
std::map<ObjectBase *, ModelConfig *> object_configs;
|
||||
bool is_object_settings = true;
|
||||
bool is_volume_settings = true;
|
||||
bool is_object_settings = false;
|
||||
bool is_volume_settings = false;
|
||||
bool is_layer_range_settings = false;
|
||||
bool is_layer_root = false;
|
||||
ModelObject * parent_object = nullptr;
|
||||
for (auto item : items) {
|
||||
auto type = objects_model->GetItemType(item);
|
||||
if (type != itObject && type != itVolume) {
|
||||
if (type != itObject && type != itVolume && type != itLayerRoot && type != itLayer) {
|
||||
continue;
|
||||
}
|
||||
const int obj_idx = objects_model->GetObjectIdByItem(item);
|
||||
assert(obj_idx >= 0);
|
||||
auto object = wxGetApp().model().objects[obj_idx];
|
||||
if (type == itObject) {
|
||||
if (!is_object_settings)
|
||||
return false;
|
||||
is_volume_settings = false;
|
||||
is_object_settings = true;
|
||||
object_configs.emplace(object, &object->config);
|
||||
} else {
|
||||
if (!is_volume_settings)
|
||||
return false;
|
||||
}
|
||||
else if(type == itVolume){
|
||||
is_volume_settings = true;
|
||||
if (parent_object && parent_object != object)
|
||||
return false;
|
||||
parent_object = object;
|
||||
is_object_settings = false;
|
||||
const int vol_idx = objects_model->GetVolumeIdByItem(item);
|
||||
assert(vol_idx >= 0);
|
||||
auto volume = object->volumes[vol_idx];
|
||||
object_configs.emplace(volume, &volume->config);
|
||||
}
|
||||
else if(type == itLayer){
|
||||
is_layer_range_settings = true;
|
||||
if (parent_object && parent_object != object)
|
||||
return false;
|
||||
parent_object = object;
|
||||
|
||||
t_layer_height_range height_range = objects_model->GetLayerRangeByItem(item);
|
||||
object_configs.emplace( (ObjectBase*)(&object->layer_config_ranges.at(height_range)), &object->layer_config_ranges.at(height_range) );
|
||||
}
|
||||
else if (type == itLayerRoot) {
|
||||
is_layer_root = true;
|
||||
}
|
||||
}
|
||||
|
||||
auto tab_object = dynamic_cast<TabPrintModel*>(wxGetApp().get_model_tab());
|
||||
auto tab_volume = dynamic_cast<TabPrintModel*>(wxGetApp().get_model_tab(true));
|
||||
auto tab_layer = dynamic_cast<TabPrintModel*>(wxGetApp().get_layer_tab());
|
||||
|
||||
if (is_volume_settings == is_object_settings) {
|
||||
tab_object->set_model_config({});
|
||||
tab_volume->set_model_config({});
|
||||
m_tab_active = nullptr;
|
||||
} else if (is_volume_settings) {
|
||||
tab_object->set_model_config({{parent_object, &parent_object->config}});
|
||||
tab_volume->set_model_config(object_configs);
|
||||
m_tab_active = tab_volume;
|
||||
} else if (is_object_settings) {
|
||||
if (is_object_settings) {
|
||||
tab_object->set_model_config(object_configs);
|
||||
tab_volume->set_model_config({});
|
||||
tab_layer->set_model_config({});
|
||||
m_tab_active = tab_object;
|
||||
}
|
||||
else if (is_volume_settings) {
|
||||
tab_object->set_model_config({ {parent_object, &parent_object->config} });
|
||||
tab_volume->set_model_config(object_configs);
|
||||
tab_layer->set_model_config({});
|
||||
m_tab_active = tab_volume;
|
||||
}
|
||||
else if (is_layer_range_settings) {
|
||||
tab_object->set_model_config({ {parent_object, &parent_object->config} });
|
||||
tab_volume->set_model_config({});
|
||||
tab_layer->set_model_config(object_configs);
|
||||
m_tab_active = tab_layer;
|
||||
}
|
||||
else {
|
||||
tab_object->set_model_config({});
|
||||
tab_volume->set_model_config({});
|
||||
tab_layer->set_model_config({});
|
||||
m_tab_active = nullptr;
|
||||
}
|
||||
((ParamsPanel*) tab_object->GetParent())->set_active_tab(nullptr);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1384,11 +1384,20 @@ wxString ObjectGridTable::GetValue (int row, int col)
|
|||
}
|
||||
else {
|
||||
try {
|
||||
ConfigOptionString& option_value = dynamic_cast<ConfigOptionString&>(option);
|
||||
if (grid_row->row_type == row_volume)
|
||||
if (grid_row->row_type == row_volume){
|
||||
ConfigOptionString& option_value = dynamic_cast<ConfigOptionString&>(option);
|
||||
return GUI::from_u8(std::string(" ") + option_value.value);
|
||||
else
|
||||
return GUI::from_u8(option_value.value);
|
||||
}
|
||||
else {
|
||||
if (option.type() == coInt) {
|
||||
ConfigOptionInt& option_value = dynamic_cast<ConfigOptionInt&>(option);
|
||||
return GUI::from_u8(wxString::Format("%d",option_value.value).ToStdString());
|
||||
}else {
|
||||
ConfigOptionString& option_value = dynamic_cast<ConfigOptionString&>(option);
|
||||
return GUI::from_u8(option_value.value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format("row %1%, col %2%, type %3% ")%row %col %grid_col->type;
|
||||
|
|
@ -2928,11 +2937,11 @@ void ObjectTablePanel::load_data()
|
|||
m_object_grid->SetCellRenderer(row, col, new GridCellIconRenderer());
|
||||
m_object_grid->SetReadOnly(row, col);
|
||||
}
|
||||
else if (grid_col->b_for_object && (grid_row->row_type == ObjectGridTable::row_volume)) {
|
||||
m_object_grid->SetReadOnly(row, col);
|
||||
m_object_grid->SetCellEditor(row, col, new wxGridCellAutoWrapStringEditor());
|
||||
m_object_grid->SetCellRenderer(row, col, new wxGridCellAutoWrapStringRenderer());
|
||||
}
|
||||
//else if (grid_col->b_for_object && (grid_row->row_type == ObjectGridTable::row_volume)) {
|
||||
// /*m_object_grid->SetReadOnly(row, col);
|
||||
// m_object_grid->SetCellEditor(row, col, new wxGridCellAutoWrapStringEditor());
|
||||
// m_object_grid->SetCellRenderer(row, col, new wxGridCellAutoWrapStringRenderer());*/
|
||||
//}
|
||||
else {
|
||||
if (!grid_col->b_editable)
|
||||
m_object_grid->SetReadOnly(row, col);
|
||||
|
|
|
|||
|
|
@ -581,12 +581,13 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
|
|||
}
|
||||
}
|
||||
m_layers_slider->SetSelectionSpan(idx_low, idx_high);
|
||||
m_layers_slider->SetTicksValues(ticks_info_from_curr_plate);
|
||||
|
||||
auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
|
||||
auto curr_print_seq = curr_plate->get_real_print_seq();
|
||||
bool sequential_print = (curr_print_seq == PrintSequence::ByObject);
|
||||
m_layers_slider->SetDrawMode(sequential_print);
|
||||
|
||||
m_layers_slider->SetTicksValues(ticks_info_from_curr_plate);
|
||||
|
||||
auto print_mode_stat = m_gcode_result->print_statistics.modes.front();
|
||||
m_layers_slider->SetLayersTimes(print_mode_stat.layers_times, print_mode_stat.time);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -3,9 +3,15 @@
|
|||
|
||||
#include "GLGizmoBase.hpp"
|
||||
#include "GLGizmoRotate.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
enum class CutConnectorType : int;
|
||||
class ModelVolume;
|
||||
struct CutConnectorAttributes;
|
||||
|
||||
namespace GUI {
|
||||
enum class SLAGizmoEventType : unsigned char;
|
||||
|
||||
class GLGizmoAdvancedCut : public GLGizmoRotate3D
|
||||
{
|
||||
|
|
@ -43,7 +49,11 @@ private:
|
|||
bool m_keep_upper;
|
||||
bool m_keep_lower;
|
||||
bool m_cut_to_parts;
|
||||
bool m_rotate_lower;
|
||||
bool m_place_on_cut_upper{true};
|
||||
bool m_place_on_cut_lower{false};
|
||||
bool m_rotate_upper{false};
|
||||
bool m_rotate_lower{false};
|
||||
|
||||
bool m_do_segment;
|
||||
double m_segment_smoothing_alpha;
|
||||
int m_segment_number;
|
||||
|
|
@ -54,25 +64,94 @@ private:
|
|||
|
||||
unsigned int m_last_active_id;
|
||||
|
||||
bool m_connectors_editing{false};
|
||||
bool m_show_shortcuts{false};
|
||||
|
||||
std::vector<std::pair<wxString, wxString>> m_shortcuts;
|
||||
double m_label_width{150.0};
|
||||
double m_control_width{ 200.0 };
|
||||
double m_editing_window_width;
|
||||
|
||||
CutConnectorType m_connector_type;
|
||||
size_t m_connector_style;
|
||||
size_t m_connector_shape_id;
|
||||
|
||||
float m_connector_depth_ratio{3.f};
|
||||
float m_connector_depth_ratio_tolerance{0.1f};
|
||||
|
||||
float m_connector_size{2.5f};
|
||||
float m_connector_size_tolerance{0.f};
|
||||
|
||||
TriangleMesh m_connector_mesh;
|
||||
bool m_has_invalid_connector{false};
|
||||
|
||||
// remember the connectors which is selected
|
||||
mutable std::vector<bool> m_selected;
|
||||
int m_selected_count{0};
|
||||
|
||||
Vec3d m_cut_plane_center{Vec3d::Zero()};
|
||||
Vec3d m_cut_plane_normal{Vec3d::UnitZ()};
|
||||
|
||||
Vec3d m_cut_line_begin{Vec3d::Zero()};
|
||||
Vec3d m_cut_line_end{Vec3d::Zero()};
|
||||
|
||||
Transform3d m_rotate_matrix{Transform3d::Identity()};
|
||||
|
||||
std::map<CutConnectorAttributes, GLModel> m_shapes;
|
||||
|
||||
struct InvalidConnectorsStatistics
|
||||
{
|
||||
unsigned int outside_cut_contour;
|
||||
unsigned int outside_bb;
|
||||
bool is_overlap;
|
||||
|
||||
void invalidate()
|
||||
{
|
||||
outside_cut_contour = 0;
|
||||
outside_bb = 0;
|
||||
is_overlap = false;
|
||||
}
|
||||
} m_info_stats;
|
||||
|
||||
//GLSelectionRectangle m_selection_rectangle;
|
||||
|
||||
public:
|
||||
GLGizmoAdvancedCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
|
||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down);
|
||||
bool on_key(wxKeyEvent &evt);
|
||||
|
||||
double get_movement() const { return m_movement; }
|
||||
void set_movement(double movement) const;
|
||||
void finish_rotation();
|
||||
std::string get_tooltip() const override;
|
||||
|
||||
BoundingBoxf3 bounding_box() const;
|
||||
//BoundingBoxf3 transformed_bounding_box(const Vec3d &plane_center, bool revert_move = false) const;
|
||||
|
||||
bool is_looking_forward() const;
|
||||
|
||||
bool unproject_on_cut_plane(const Vec2d &mouse_pos, Vec3d &pos, Vec3d &pos_world);
|
||||
|
||||
virtual bool apply_clipping_plane() { return m_connectors_editing; }
|
||||
|
||||
protected:
|
||||
virtual bool on_init();
|
||||
virtual void on_load(cereal::BinaryInputArchive &ar) override;
|
||||
virtual void on_save(cereal::BinaryOutputArchive &ar) const override;
|
||||
virtual std::string on_get_name() const;
|
||||
virtual void on_set_state();
|
||||
virtual bool on_is_activable() const;
|
||||
virtual void on_start_dragging();
|
||||
virtual CommonGizmosDataID on_get_requirements() const override;
|
||||
virtual void on_start_dragging() override;
|
||||
virtual void on_stop_dragging() override;
|
||||
virtual void on_update(const UpdateData& data);
|
||||
virtual void on_render();
|
||||
virtual void on_render_for_picking();
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit);
|
||||
|
||||
void show_tooltip_information(float x, float y);
|
||||
|
||||
virtual void on_enable_grabber(unsigned int id)
|
||||
{
|
||||
if (id < 3)
|
||||
|
|
@ -97,6 +176,12 @@ protected:
|
|||
|
||||
private:
|
||||
void perform_cut(const Selection& selection);
|
||||
bool can_perform_cut() const;
|
||||
void apply_connectors_in_model(ModelObject *mo, bool &create_dowels_as_separate_object);
|
||||
|
||||
bool is_selection_changed(bool alt_down, bool shift_down);
|
||||
void select_connector(int idx, bool select);
|
||||
|
||||
double calc_projection(const Linef3& mouse_ray) const;
|
||||
Vec3d calc_plane_normal(const std::array<Vec3d, 4>& plane_points) const;
|
||||
Vec3d calc_plane_center(const std::array<Vec3d, 4>& plane_points) const;
|
||||
|
|
@ -107,6 +192,46 @@ private:
|
|||
std::array<Vec3d, 4> get_plane_points_world_coord() const;
|
||||
void reset_cut_plane();
|
||||
void reset_all();
|
||||
|
||||
// update the connectors position so that the connectors are on the cut plane
|
||||
void put_connectors_on_cut_plane(const Vec3d &cp_normal, double cp_offset);
|
||||
void update_clipper();
|
||||
// on render
|
||||
void render_cut_plane_and_grabbers();
|
||||
void render_connectors();
|
||||
void render_clipper_cut();
|
||||
void render_cut_line();
|
||||
void render_connector_model(GLModel &model, const std::array<float, 4>& color, Transform3d view_model_matrix, bool for_picking = false);
|
||||
|
||||
void clear_selection();
|
||||
void init_connector_shapes();
|
||||
void set_connectors_editing(bool connectors_editing);
|
||||
void reset_connectors();
|
||||
void update_connector_shape();
|
||||
void apply_selected_connectors(std::function<void(size_t idx)> apply_fn);
|
||||
void select_all_connectors();
|
||||
void unselect_all_connectors();
|
||||
void validate_connector_settings();
|
||||
bool add_connector(CutConnectors &connectors, const Vec2d &mouse_position);
|
||||
bool delete_selected_connectors();
|
||||
bool is_outside_of_cut_contour(size_t idx, const CutConnectors &connectors, const Vec3d cur_pos);
|
||||
bool is_conflict_for_connector(size_t idx, const CutConnectors &connectors, const Vec3d cur_pos);
|
||||
void check_conflict_for_all_connectors();
|
||||
|
||||
// render input window
|
||||
void render_cut_plane_input_window(float x, float y, float bottom_limit);
|
||||
void init_connectors_input_window_data();
|
||||
void render_connectors_input_window(float x, float y, float bottom_limit);
|
||||
void render_input_window_warning() const;
|
||||
bool render_reset_button(const std::string &label_id, const std::string &tooltip) const;
|
||||
bool render_connect_type_radio_button(CutConnectorType type);
|
||||
|
||||
bool render_combo(const std::string &label, const std::vector<std::string> &lines, size_t &selection_idx);
|
||||
bool render_slider_double_input(const std::string &label, float &value_in, float &tolerance_in);
|
||||
|
||||
bool cut_line_processing() const;
|
||||
void discard_cut_line_processing();
|
||||
bool process_cut_line(SLAGizmoEventType action, const Vec2d &mouse_position);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
|||
|
|
@ -162,6 +162,8 @@ public:
|
|||
virtual std::string get_action_snapshot_name() { return "Gizmo action"; }
|
||||
void set_common_data_pool(CommonGizmosDataPool* ptr) { m_c = ptr; }
|
||||
|
||||
virtual bool apply_clipping_plane() { return true; }
|
||||
|
||||
unsigned int get_sprite_id() const { return m_sprite_id; }
|
||||
|
||||
int get_hover_id() const { return m_hover_id; }
|
||||
|
|
|
|||
|
|
@ -336,8 +336,8 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
|||
if (action == SLAGizmoEventType::LeftUp) {
|
||||
if (m_wait_for_up_event) {
|
||||
m_wait_for_up_event = false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// dragging the selection rectangle:
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ bool GLGizmoRotate::on_init()
|
|||
void GLGizmoRotate::on_start_dragging()
|
||||
{
|
||||
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
||||
m_center = box.center();
|
||||
m_center = m_custom_center == Vec3d::Zero() ? box.center() : m_custom_center;
|
||||
m_radius = Offset + box.radius();
|
||||
m_snap_coarse_in_radius = m_radius / 3.0f;
|
||||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||
|
|
@ -135,7 +135,7 @@ void GLGizmoRotate::on_render()
|
|||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
|
||||
if (m_hover_id != 0 && !m_grabbers[0].dragging) {
|
||||
m_center = box.center();
|
||||
m_center = m_custom_center == Vec3d::Zero() ? box.center() : m_custom_center;
|
||||
m_radius = Offset + box.radius();
|
||||
m_snap_coarse_in_radius = m_radius / 3.0f;
|
||||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ private:
|
|||
Axis m_axis;
|
||||
double m_angle;
|
||||
|
||||
mutable Vec3d m_custom_center{Vec3d::Zero()};
|
||||
mutable Vec3d m_center;
|
||||
mutable float m_radius;
|
||||
|
||||
|
|
@ -52,6 +53,8 @@ public:
|
|||
|
||||
std::string get_tooltip() const override;
|
||||
|
||||
void set_center(const Vec3d &point) { m_custom_center = point; }
|
||||
|
||||
protected:
|
||||
bool on_init() override;
|
||||
std::string on_get_name() const override { return ""; }
|
||||
|
|
@ -101,6 +104,13 @@ public:
|
|||
return tooltip;
|
||||
}
|
||||
|
||||
void set_center(const Vec3d &point)
|
||||
{
|
||||
m_gizmos[X].set_center(point);
|
||||
m_gizmos[Y].set_center(point);
|
||||
m_gizmos[Z].set_center(point);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool on_init() override;
|
||||
std::string on_get_name() const override;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,12 @@ std::string GLGizmoScale3D::get_tooltip() const
|
|||
return "";
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::enable_ununiversal_scale(bool enable)
|
||||
{
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
m_grabbers[i].enabled = enable;
|
||||
}
|
||||
|
||||
bool GLGizmoScale3D::on_init()
|
||||
{
|
||||
for (int i = 0; i < 10; ++i)
|
||||
|
|
@ -228,9 +234,11 @@ void GLGizmoScale3D::on_render()
|
|||
|
||||
// BBS: when select multiple objects, uniform scale can be deselected, display the connection(4,5)
|
||||
//if (single_instance || single_volume) {
|
||||
|
||||
if (m_grabbers[4].enabled && m_grabbers[5].enabled) {
|
||||
glsafe(::glColor4fv(m_grabbers[4].color.data()));
|
||||
render_grabbers_connection(4, 5);
|
||||
//}
|
||||
}
|
||||
|
||||
glsafe(::glColor4fv(m_grabbers[2].color.data()));
|
||||
render_grabbers_connection(6, 7);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
|
||||
std::string get_tooltip() const override;
|
||||
|
||||
void enable_ununiversal_scale(bool enable);
|
||||
protected:
|
||||
virtual bool on_init() override;
|
||||
virtual std::string on_get_name() const override;
|
||||
|
|
|
|||
|
|
@ -427,8 +427,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
if (action == SLAGizmoEventType::LeftUp) {
|
||||
if (m_wait_for_up_event) {
|
||||
m_wait_for_up_event = false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// dragging the selection rectangle:
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#endif
|
||||
#include <imgui/imgui_internal.h>
|
||||
#include "libslic3r/SVG.hpp"
|
||||
#include <codecvt>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
|
@ -228,13 +229,6 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit
|
|||
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
|
||||
const Camera & camera = wxGetApp().plater()->get_camera();
|
||||
|
||||
// Precalculate transformations of individual meshes.
|
||||
std::vector<Transform3d> trafo_matrices;
|
||||
for (const ModelVolume *mv : mo->volumes) {
|
||||
if (mv->is_model_part()) {
|
||||
trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix());
|
||||
}
|
||||
}
|
||||
if (action == SLAGizmoEventType::Moving) {
|
||||
if (shift_down && !alt_down && !control_down) {
|
||||
float angle = m_rotate_angle + 0.5 * (m_mouse_position - mouse_position).y();
|
||||
|
|
@ -265,6 +259,23 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit
|
|||
if (m_is_modify)
|
||||
return true;
|
||||
|
||||
Plater *plater = wxGetApp().plater();
|
||||
if (!plater)
|
||||
return true;
|
||||
|
||||
ModelObject *model_object = selection.get_model()->objects[m_object_idx];
|
||||
if (m_preview_text_volume_id > 0) {
|
||||
model_object->delete_volume(m_preview_text_volume_id);
|
||||
plater->update();
|
||||
m_preview_text_volume_id = -1;
|
||||
}
|
||||
|
||||
// Precalculate transformations of individual meshes.
|
||||
std::vector<Transform3d> trafo_matrices;
|
||||
for (const ModelVolume *mv : mo->volumes) {
|
||||
if (mv->is_model_part()) { trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix()); }
|
||||
}
|
||||
|
||||
Vec3f normal = Vec3f::Zero();
|
||||
Vec3f hit = Vec3f::Zero();
|
||||
size_t facet = 0;
|
||||
|
|
@ -275,9 +286,6 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit
|
|||
|
||||
// Cast a ray on all meshes, pick the closest hit and save it for the respective mesh
|
||||
for (int mesh_id = 0; mesh_id < int(trafo_matrices.size()); ++mesh_id) {
|
||||
if (mesh_id == m_preview_text_volume_id)
|
||||
continue;
|
||||
|
||||
MeshRaycaster mesh_raycaster = MeshRaycaster(mo->volumes[mesh_id]->mesh());
|
||||
|
||||
if (mesh_raycaster.unproject_on_mesh(mouse_position, trafo_matrices[mesh_id], camera, hit, normal,
|
||||
|
|
@ -302,17 +310,6 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit
|
|||
|
||||
m_rr = {mouse_position, closest_hit_mesh_id, closest_hit, closest_normal};
|
||||
|
||||
Plater *plater = wxGetApp().plater();
|
||||
if (!plater)
|
||||
return true;
|
||||
|
||||
ModelObject *model_object = selection.get_model()->objects[m_object_idx];
|
||||
if (m_preview_text_volume_id > 0) {
|
||||
model_object->delete_volume(m_preview_text_volume_id);
|
||||
plater->update();
|
||||
m_preview_text_volume_id = -1;
|
||||
}
|
||||
|
||||
m_is_modify = true;
|
||||
generate_text_volume(false);
|
||||
plater->update();
|
||||
|
|
@ -937,10 +934,9 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
|||
} else {
|
||||
alpha = texts[i];
|
||||
}
|
||||
TriangleMesh mesh;
|
||||
load_text_shape(alpha.c_str(), m_font_name.c_str(), m_font_size, m_thickness + m_embeded_depth, m_bold, m_italic, mesh);
|
||||
auto center = mesh.bounding_box().center();
|
||||
double half_x_length = center.x();
|
||||
TextResult text_result;
|
||||
load_text_shape(alpha.c_str(), m_font_name.c_str(), m_font_size, m_thickness + m_embeded_depth, m_bold, m_italic, text_result);
|
||||
double half_x_length = text_result.text_width / 2;
|
||||
text_lengths.emplace_back(half_x_length);
|
||||
}
|
||||
|
||||
|
|
@ -978,20 +974,25 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
|||
|
||||
TriangleMesh slice_meshs;
|
||||
int mesh_index = 0;
|
||||
int volume_index = 0;
|
||||
for (int i = 0; i < mo->volumes.size(); ++i) {
|
||||
// skip the editing text volume
|
||||
if (m_is_modify && m_volume_idx == i)
|
||||
continue;
|
||||
|
||||
ModelVolume *mv = mo->volumes[i];
|
||||
if (mv->is_model_part()) {
|
||||
if (mesh_index == m_rr.mesh_id) {
|
||||
TriangleMesh vol_mesh(mv->mesh());
|
||||
vol_mesh.transform(mv->get_matrix());
|
||||
slice_meshs = vol_mesh;
|
||||
break;
|
||||
volume_index = i;
|
||||
}
|
||||
TriangleMesh vol_mesh(mv->mesh());
|
||||
vol_mesh.transform(mv->get_matrix());
|
||||
slice_meshs.merge(vol_mesh);
|
||||
mesh_index++;
|
||||
}
|
||||
}
|
||||
|
||||
ModelVolume* volume = mo->volumes[mesh_index];
|
||||
ModelVolume* volume = mo->volumes[volume_index];
|
||||
|
||||
Vec3d temp_position = m_mouse_position_world;
|
||||
Vec3d temp_normal = m_mouse_normal_world;
|
||||
|
|
@ -1093,7 +1094,7 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
|||
// for debug
|
||||
//export_regions_to_svg(Point(m_mouse_position_world.x(), m_mouse_position_world.y()), temp_polys);
|
||||
|
||||
Polygons polys = temp_polys;
|
||||
Polygons polys = union_(temp_polys);
|
||||
|
||||
auto point_in_line_rectange = [](const Line &line, const Point &point, double& distance) {
|
||||
distance = abs((point.x() - line.a.x()) * (line.b.y() - line.a.y()) - (line.b.x() - line.a.x()) * (point.y() - line.a.y()));
|
||||
|
|
@ -1354,13 +1355,13 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
|||
|
||||
TriangleMesh GLGizmoText::get_text_mesh(const char* text_str, const Vec3d &position, const Vec3d &normal, const Vec3d& text_up_dir)
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
load_text_shape(text_str, m_font_name.c_str(), m_font_size, m_thickness + m_embeded_depth, m_bold, m_italic, mesh);
|
||||
TextResult text_result;
|
||||
load_text_shape(text_str, m_font_name.c_str(), m_font_size, m_thickness + m_embeded_depth, m_bold, m_italic, text_result);
|
||||
TriangleMesh mesh = text_result.text_mesh;
|
||||
|
||||
auto center = mesh.bounding_box().center();
|
||||
double mesh_offset = center.z();
|
||||
|
||||
mesh.translate(-center.x(), -m_font_size / 4, -center.z());
|
||||
mesh.translate(-text_result.text_width / 2, -m_font_size / 4, -center.z());
|
||||
|
||||
double phi;
|
||||
Vec3d rotation_axis;
|
||||
|
|
@ -1377,6 +1378,11 @@ TriangleMesh GLGizmoText::get_text_mesh(const char* text_str, const Vec3d &posit
|
|||
Vec3d new_text_dir = project_on_plane(text_up_dir, normal);
|
||||
new_text_dir.normalize();
|
||||
Geometry::rotation_from_two_vectors(old_text_dir, new_text_dir, rotation_axis, phi, &rotation_matrix);
|
||||
|
||||
static double const PI = 3.141592653589793238;
|
||||
if (abs(phi - PI) < EPSILON)
|
||||
rotation_axis = normal;
|
||||
|
||||
mesh.rotate(phi, rotation_axis);
|
||||
|
||||
const Selection & selection = m_parent.get_selection();
|
||||
|
|
@ -1438,10 +1444,11 @@ void GLGizmoText::generate_text_volume(bool is_temp)
|
|||
if (text.empty())
|
||||
return;
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> str_cnv;
|
||||
std::wstring ws = boost::nowide::widen(m_text);
|
||||
std::vector<std::string> alphas;
|
||||
if (!get_utf8_sub_strings(m_text, strlen(m_text), alphas)) {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("Text: input text is not utf8");
|
||||
return;
|
||||
for (auto w : ws) {
|
||||
alphas.push_back(str_cnv.to_bytes(w));
|
||||
}
|
||||
|
||||
update_text_positions(alphas);
|
||||
|
|
|
|||
|
|
@ -449,7 +449,26 @@ void ObjectClipper::set_position(double pos, bool keep_normal)
|
|||
get_pool()->get_canvas()->set_as_dirty();
|
||||
}
|
||||
|
||||
void ObjectClipper::set_range_and_pos(const Vec3d &cpl_normal, double cpl_offset, double pos)
|
||||
{
|
||||
m_clp.reset(new ClippingPlane(cpl_normal, cpl_offset));
|
||||
m_clp_ratio = pos;
|
||||
get_pool()->get_canvas()->set_as_dirty();
|
||||
}
|
||||
|
||||
bool ObjectClipper::is_projection_inside_cut(const Vec3d &point) const
|
||||
{
|
||||
return m_clp_ratio != 0. && std::any_of(m_clippers.begin(), m_clippers.end(), [point](const auto &cl) {
|
||||
return cl->is_projection_inside_cut(point);
|
||||
});
|
||||
}
|
||||
|
||||
bool ObjectClipper::has_valid_contour() const
|
||||
{
|
||||
return m_clp_ratio != 0. && std::any_of(m_clippers.begin(), m_clippers.end(), [](const auto &cl) {
|
||||
return cl->has_valid_contour();
|
||||
});
|
||||
}
|
||||
|
||||
void SupportsClipper::on_update()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -266,6 +266,10 @@ public:
|
|||
ClippingPlane* get_clipping_plane() const { return m_clp.get(); }
|
||||
void render_cut() const;
|
||||
|
||||
void set_range_and_pos(const Vec3d &cpl_normal, double cpl_offset, double pos);
|
||||
|
||||
bool is_projection_inside_cut(const Vec3d &point_in) const;
|
||||
bool has_valid_contour() const;
|
||||
|
||||
protected:
|
||||
void on_update() override;
|
||||
|
|
|
|||
|
|
@ -627,6 +627,8 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
|
|||
return dynamic_cast<GLGizmoMmuSegmentation*>(m_gizmos[MmuSegmentation].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == Text)
|
||||
return dynamic_cast<GLGizmoText*>(m_gizmos[Text].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == Cut)
|
||||
return dynamic_cast<GLGizmoAdvancedCut *>(m_gizmos[Cut].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
|
@ -872,7 +874,8 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
|
|||
m_tooltip.clear();
|
||||
|
||||
if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) {
|
||||
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Text)
|
||||
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports ||
|
||||
m_current == Seam || m_current == MmuSegmentation || m_current == Text || m_current == Cut)
|
||||
&& gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown()))
|
||||
// the gizmo got the event and took some action, there is no need to do anything more
|
||||
processed = true;
|
||||
|
|
@ -902,7 +905,8 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
|
|||
// event was taken care of by the SlaSupports gizmo
|
||||
processed = true;
|
||||
}
|
||||
else if (evt.RightDown() && !control_down && selected_object_idx != -1 && (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation)
|
||||
else if (evt.RightDown() && !control_down && selected_object_idx != -1
|
||||
&& (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Cut)
|
||||
&& gizmo_event(SLAGizmoEventType::RightDown, mouse_pos)) {
|
||||
// event was taken care of by the FdmSupports / Seam / MMUPainting gizmo
|
||||
processed = true;
|
||||
|
|
@ -911,7 +915,8 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
|
|||
&& (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation))
|
||||
// don't allow dragging objects with the Sla gizmo on
|
||||
processed = true;
|
||||
else if (evt.Dragging() && !control_down && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation)
|
||||
else if (evt.Dragging() && !control_down
|
||||
&& (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Cut)
|
||||
&& gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown())) {
|
||||
// the gizmo got the event and took some action, no need to do anything more here
|
||||
m_parent.set_as_dirty();
|
||||
|
|
@ -924,10 +929,12 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
|
|||
else if (evt.RightIsDown())
|
||||
gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), true);
|
||||
}
|
||||
else if (evt.LeftUp() && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) && !m_parent.is_mouse_dragging()) {
|
||||
else if (evt.LeftUp()
|
||||
&& (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Cut)
|
||||
&& !m_parent.is_mouse_dragging()
|
||||
&& gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down)) {
|
||||
// in case SLA/FDM gizmo is selected, we just pass the LeftUp event and stop processing - neither
|
||||
// object moving or selecting is suppressed in that case
|
||||
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down);
|
||||
processed = true;
|
||||
}
|
||||
else if (evt.LeftUp() && m_current == Flatten && m_gizmos[m_current]->get_hover_id() != -1) {
|
||||
|
|
@ -937,8 +944,9 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
|
|||
//wxGetApp().obj_manipul()->set_dirty();
|
||||
processed = true;
|
||||
}
|
||||
else if (evt.RightUp() && (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) && !m_parent.is_mouse_dragging()) {
|
||||
gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down);
|
||||
else if (evt.RightUp() && (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Cut)
|
||||
&& !m_parent.is_mouse_dragging()
|
||||
&& gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down)) {
|
||||
processed = true;
|
||||
}
|
||||
else if (evt.LeftUp()) {
|
||||
|
|
@ -1017,8 +1025,6 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt)
|
|||
break;
|
||||
}
|
||||
//skip some keys when gizmo
|
||||
case 'r':
|
||||
case 'R':
|
||||
case 'A':
|
||||
case 'a':
|
||||
{
|
||||
|
|
@ -1088,9 +1094,9 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt)
|
|||
// BBS: Skip all keys when in gizmo. This is necessary for 3D text tool.
|
||||
default:
|
||||
{
|
||||
if (is_running() && m_current == EType::Text) {
|
||||
processed = true;
|
||||
}
|
||||
//if (is_running() && m_current == EType::Text) {
|
||||
// processed = true;
|
||||
//}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1113,6 +1119,13 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
|
|||
const int keyCode = evt.GetKeyCode();
|
||||
bool processed = false;
|
||||
|
||||
// todo: zhimin Each gizmo should handle key event in it own on_key() function
|
||||
if (m_current == Cut) {
|
||||
if (GLGizmoAdvancedCut *gizmo_cut = dynamic_cast<GLGizmoAdvancedCut *>(get_current())) {
|
||||
return gizmo_cut->on_key(evt);
|
||||
}
|
||||
}
|
||||
|
||||
if (evt.GetEventType() == wxEVT_KEY_UP)
|
||||
{
|
||||
if (m_current == SlaSupports || m_current == Hollow)
|
||||
|
|
@ -1481,6 +1494,11 @@ GLGizmoBase* GLGizmosManager::get_current() const
|
|||
return ((m_current == Undefined) || m_gizmos.empty()) ? nullptr : m_gizmos[m_current].get();
|
||||
}
|
||||
|
||||
GLGizmoBase* GLGizmosManager::get_gizmo(GLGizmosManager::EType type) const
|
||||
{
|
||||
return ((type == Undefined) || m_gizmos.empty()) ? nullptr : m_gizmos[type].get();
|
||||
}
|
||||
|
||||
GLGizmosManager::EType GLGizmosManager::get_gizmo_from_name(const std::string& gizmo_name) const
|
||||
{
|
||||
std::vector<size_t> selectable_idxs = get_selectable_idxs();
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ public:
|
|||
|
||||
EType get_current_type() const { return m_current; }
|
||||
GLGizmoBase* get_current() const;
|
||||
GLGizmoBase *get_gizmo(GLGizmosManager::EType type) const;
|
||||
EType get_gizmo_from_name(const std::string& gizmo_name) const;
|
||||
|
||||
bool is_running() const;
|
||||
|
|
@ -311,7 +312,7 @@ public:
|
|||
//BBS: GUI refactor: GLToolbar adjust
|
||||
float get_scaled_total_height() const;
|
||||
float get_scaled_total_width() const;
|
||||
//GizmoObjectManipulation& get_object_manipulation() { return m_object_manipulation; }
|
||||
GizmoObjectManipulation& get_object_manipulation() { return m_object_manipulation; }
|
||||
bool get_uniform_scaling() const { return m_object_manipulation.get_uniform_scaling();}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -330,8 +330,11 @@ void GizmoObjectManipulation::change_size_value(int axis, double value)
|
|||
const Selection& selection = m_glcanvas.get_selection();
|
||||
|
||||
Vec3d ref_size = m_cache.size;
|
||||
if (selection.is_single_volume() || selection.is_single_modifier())
|
||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
Vec3d instance_scale = wxGetApp().model().objects[selection.get_volume(*selection.get_volume_idxs().begin())->object_idx()]->instances[0]->get_transformation().get_scaling_factor();
|
||||
ref_size = selection.get_volume(*selection.get_volume_idxs().begin())->bounding_box().size();
|
||||
ref_size = Vec3d(instance_scale[0] * ref_size[0], instance_scale[1] * ref_size[1], instance_scale[2] * ref_size[2]);
|
||||
}
|
||||
else if (selection.is_single_full_instance())
|
||||
ref_size = m_world_coordinates ?
|
||||
selection.get_unscaled_instance_bounding_box().size() :
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ static std::string gcode(Type type)
|
|||
switch (type) {
|
||||
//BBS
|
||||
case Template: return config.opt_string("template_custom_gcode");
|
||||
case PausePrint: return config.opt_string("machine_pause_gcode");
|
||||
|
||||
default: return "";
|
||||
}
|
||||
|
||||
|
|
@ -150,6 +152,7 @@ bool IMSlider::init_texture()
|
|||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/one_layer_off_dark.svg", 28, 28, m_one_layer_off_dark_id);
|
||||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/one_layer_off_hover_dark.svg", 28, 28, m_one_layer_off_hover_dark_id);
|
||||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/im_gcode_pause.svg", 14, 14, m_pause_icon_id);
|
||||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/im_gcode_custom.svg", 14, 14, m_custom_icon_id);
|
||||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/im_slider_delete.svg", 14, 14, m_delete_icon_id);
|
||||
}
|
||||
|
||||
|
|
@ -224,6 +227,8 @@ void IMSlider::SetTicksValues(const Info &custom_gcode_per_print_z)
|
|||
return;
|
||||
}
|
||||
|
||||
static bool last_spiral_vase_status = false;
|
||||
|
||||
const bool was_empty = m_ticks.empty();
|
||||
|
||||
m_ticks.ticks.clear();
|
||||
|
|
@ -242,6 +247,30 @@ void IMSlider::SetTicksValues(const Info &custom_gcode_per_print_z)
|
|||
post_ticks_changed_event();
|
||||
}
|
||||
|
||||
if (last_spiral_vase_status != m_is_spiral_vase) {
|
||||
last_spiral_vase_status = m_is_spiral_vase;
|
||||
if (!m_ticks.empty()) {
|
||||
m_ticks.ticks.clear();
|
||||
post_ticks_changed_event();
|
||||
}
|
||||
}
|
||||
|
||||
//auto has_tick_execpt = [this](CustomGCode::Type type) {
|
||||
// for (const TickCode& tick : m_ticks.ticks)
|
||||
// if (tick.type != type) return true;
|
||||
|
||||
// return false;
|
||||
//};
|
||||
if ((!m_ticks.empty() /*&& has_tick_execpt(PausePrint)*/) && m_draw_mode == dmSequentialFffPrint) {
|
||||
for (auto it{ m_ticks.ticks.begin() }, end{ m_ticks.ticks.end() }; it != end;) {
|
||||
if (true/*it->type != PausePrint*/)
|
||||
it = m_ticks.ticks.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
post_ticks_changed_event();
|
||||
}
|
||||
|
||||
if (custom_gcode_per_print_z.mode && !custom_gcode_per_print_z.gcodes.empty()) m_ticks.mode = custom_gcode_per_print_z.mode;
|
||||
|
||||
set_as_dirty();
|
||||
|
|
@ -282,6 +311,7 @@ void IMSlider::SetDrawMode(bool is_sequential_print)
|
|||
{
|
||||
m_draw_mode = is_sequential_print ? dmSequentialFffPrint :
|
||||
dmRegular;
|
||||
m_can_change_color = m_can_change_color && !(m_draw_mode == dmSequentialFffPrint);
|
||||
}
|
||||
|
||||
void IMSlider::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder, bool can_change_color)
|
||||
|
|
@ -292,18 +322,12 @@ void IMSlider::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model,
|
|||
|
||||
UseDefaultColors(m_mode == SingleExtruder);
|
||||
|
||||
auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
|
||||
auto curr_print_seq = curr_plate->get_real_print_seq();
|
||||
|
||||
if (curr_print_seq == PrintSequence::ByObject)
|
||||
m_is_wipe_tower = false;
|
||||
else
|
||||
m_is_wipe_tower = m_mode != SingleExtruder;
|
||||
m_is_wipe_tower = m_mode != SingleExtruder;
|
||||
|
||||
auto config = wxGetApp().preset_bundle->full_config();
|
||||
m_is_spiral_vase = config.option<ConfigOptionBool>("spiral_mode")->value;
|
||||
|
||||
m_can_change_color = can_change_color;
|
||||
m_can_change_color = can_change_color && !m_is_spiral_vase;
|
||||
|
||||
// close opened menu window after reslice
|
||||
m_show_menu = false;
|
||||
|
|
@ -376,6 +400,11 @@ void IMSlider::add_code_as_tick(Type type, int selected_extruder)
|
|||
post_ticks_changed_event(type);
|
||||
}
|
||||
|
||||
void IMSlider::delete_tick(const TickCode& tick) {
|
||||
m_ticks.ticks.erase(tick);
|
||||
post_ticks_changed_event(tick.type);
|
||||
}
|
||||
|
||||
bool IMSlider::check_ticks_changed_event(Type type)
|
||||
{
|
||||
//BBL only support MultiExtruder
|
||||
|
|
@ -623,12 +652,16 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
|
|||
if (ImGui::IsMouseHoveringRect(tick_hover_box.Min, tick_hover_box.Max))
|
||||
{
|
||||
// render left tick box
|
||||
ImGui::RenderFrame(tick_hover_box.Min, { slideable_region.Min.x, tick_hover_box.Max.y }, tick_hover_box_clr, false);
|
||||
ImRect left_hover_box = ImRect(tick_hover_box.Min, { slideable_region.Min.x, tick_hover_box.Max.y });
|
||||
ImGui::RenderFrame(left_hover_box.Min, left_hover_box.Max, tick_hover_box_clr, false);
|
||||
// render right tick box
|
||||
ImGui::RenderFrame({ slideable_region.Max.x, tick_hover_box.Min.y }, tick_hover_box.Max, tick_hover_box_clr, false);
|
||||
ImRect right_hover_box = ImRect({ slideable_region.Max.x, tick_hover_box.Min.y }, tick_hover_box.Max);
|
||||
ImGui::RenderFrame(right_hover_box.Min, right_hover_box.Max, tick_hover_box_clr, false);
|
||||
|
||||
show_tooltip(*tick_it);
|
||||
if (context.IO.MouseClicked[0]) {
|
||||
m_tick_value = tick_it->tick;
|
||||
m_tick_rect = ImVec4(tick_hover_box.Min.x, tick_hover_box.Min.y, tick_hover_box.Max.x, tick_hover_box.Max.y);
|
||||
m_tick_value = tick_it->tick;
|
||||
m_tick_rect = ImVec4(tick_hover_box.Min.x, tick_hover_box.Min.y, tick_hover_box.Max.x, tick_hover_box.Max.y);
|
||||
}
|
||||
}
|
||||
++tick_it;
|
||||
|
|
@ -651,6 +684,11 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
|
|||
ImVec2 icon_pos = ImVec2(slideable_region.GetCenter().x + icon_offset.x, tick_pos - icon_offset.y);
|
||||
button_with_pos(pause_icon_id, icon_size, icon_pos);
|
||||
}
|
||||
if (tick_it->type == Custom || tick_it->type == Template) {
|
||||
ImTextureID custom_icon_id = m_custom_icon_id;
|
||||
ImVec2 icon_pos = ImVec2(slideable_region.GetCenter().x + icon_offset.x, tick_pos - icon_offset.y);
|
||||
button_with_pos(custom_icon_id, icon_size, icon_pos);
|
||||
}
|
||||
++tick_it;
|
||||
}
|
||||
|
||||
|
|
@ -664,13 +702,45 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
|
|||
if (ImGui::IsMouseHoveringRect(icon_pos, icon_pos + icon_size)) {
|
||||
if (context.IO.MouseClicked[0]) {
|
||||
// delete tick
|
||||
Type type = tick_it->type;
|
||||
m_ticks.ticks.erase(tick_it);
|
||||
post_ticks_changed_event(type);
|
||||
delete_tick(*tick_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMSlider::show_tooltip(const std::string tooltip) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 6 * m_scale, 3 * m_scale });
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, { 3 * m_scale });
|
||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, { 0,0,0,0 });
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.00f, 1.00f, 1.00f, 1.00f));
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(tooltip.c_str());
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
void IMSlider::show_tooltip(const TickCode& tick){
|
||||
switch (tick.type)
|
||||
{
|
||||
case CustomGCode::ColorChange:
|
||||
break;
|
||||
case CustomGCode::PausePrint:
|
||||
show_tooltip(_u8L("Pause:") + " \"" + gcode(PausePrint) + "\"");
|
||||
break;
|
||||
case CustomGCode::ToolChange:
|
||||
show_tooltip(_u8L("Change Filament"));
|
||||
break;
|
||||
case CustomGCode::Template:
|
||||
show_tooltip(_u8L("Custom Template:") + " \"" + gcode(Template) + "\"");
|
||||
break;
|
||||
case CustomGCode::Custom:
|
||||
show_tooltip(_u8L("Custom G-code:") + " \"" + tick.extra + "\"");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower_value, std::string& higher_label, std::string& lower_label,int v_min, int v_max, const ImVec2& size, SelectedSlider& selection, bool one_layer_flag, float scale)
|
||||
|
|
@ -790,12 +860,10 @@ bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower
|
|||
context.IO.MouseClicked[0])
|
||||
m_show_menu = false;
|
||||
|
||||
if (!m_ticks.empty()) {
|
||||
// draw ticks
|
||||
draw_ticks(h_selected ? higher_slideable_region : lower_slideable_region);
|
||||
// draw colored band
|
||||
draw_colored_band(groove, h_selected ? higher_slideable_region : lower_slideable_region);
|
||||
}
|
||||
// draw ticks
|
||||
draw_ticks(h_selected ? higher_slideable_region : lower_slideable_region);
|
||||
// draw colored band
|
||||
draw_colored_band(groove, h_selected ? higher_slideable_region : lower_slideable_region);
|
||||
|
||||
if (!m_ticks.has_tick_with_code(ToolChange)) {
|
||||
// draw scroll line
|
||||
|
|
@ -862,12 +930,10 @@ bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower
|
|||
|
||||
ImVec2 bar_center = higher_handle.GetCenter();
|
||||
|
||||
if (!m_ticks.empty()) {
|
||||
// draw ticks
|
||||
draw_ticks(one_slideable_region);
|
||||
// draw colored band
|
||||
draw_colored_band(groove, one_slideable_region);
|
||||
}
|
||||
// draw ticks
|
||||
draw_ticks(one_slideable_region);
|
||||
// draw colored band
|
||||
draw_colored_band(groove, one_slideable_region);
|
||||
|
||||
// draw handle
|
||||
window->DrawList->AddLine(ImVec2(mid_x - 0.5 * bar_width, handle_center.y), ImVec2(mid_x + 0.5 * bar_width, handle_center.y), handle_clr, 2 * line_width);
|
||||
|
|
@ -963,7 +1029,7 @@ bool IMSlider::render(int canvas_width, int canvas_height)
|
|||
return result;
|
||||
}
|
||||
|
||||
void IMSlider::render_input_custom_gcode()
|
||||
void IMSlider::render_input_custom_gcode(std::string custom_gcode)
|
||||
{
|
||||
if (m_show_custom_gcode_window)
|
||||
ImGui::OpenPopup((_u8L("Custom G-code")).c_str());
|
||||
|
|
@ -995,9 +1061,13 @@ void IMSlider::render_input_custom_gcode()
|
|||
if (set_focus && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)) {
|
||||
wxGetApp().plater()->get_current_canvas3D()->force_set_focus();
|
||||
ImGui::SetKeyboardFocusHere(0);
|
||||
strcpy(m_custom_gcode, custom_gcode.c_str());
|
||||
}
|
||||
const int text_height = 6;
|
||||
ImGui::InputTextMultiline("##text", m_custom_gcode, sizeof(m_custom_gcode), ImVec2(-1, ImGui::GetTextLineHeight() * text_height));
|
||||
|
||||
ImGui::InputTextMultiline("##text", m_custom_gcode, sizeof(m_custom_gcode), ImVec2(-1, ImGui::GetTextLineHeight() * text_height), ImGuiInputTextFlags_CallbackAlways, [](ImGuiInputTextCallbackData* data) {
|
||||
return data->CursorPos = data->BufTextLen;
|
||||
});
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::SameLine(ImGui::GetStyle().WindowPadding.x * 14);
|
||||
|
|
@ -1046,7 +1116,7 @@ void IMSlider::do_go_to_layer(size_t layer_number) {
|
|||
void IMSlider::render_go_to_layer_dialog()
|
||||
{
|
||||
if (m_show_go_to_layer_dialog)
|
||||
ImGui::OpenPopup((_u8L("Jump to layer")).c_str());
|
||||
ImGui::OpenPopup((_u8L("Jump to Layer")).c_str());
|
||||
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||
|
|
@ -1123,37 +1193,61 @@ void IMSlider::render_go_to_layer_dialog()
|
|||
imgui.pop_menu_style();
|
||||
}
|
||||
|
||||
void IMSlider::render_menu()
|
||||
{
|
||||
ImGuiWrapper::push_menu_style(m_scale);
|
||||
int extruder_num = m_extruder_colors.size();
|
||||
void IMSlider::render_menu() {
|
||||
if (!m_menu_enable)
|
||||
return;
|
||||
|
||||
if (m_show_menu) {
|
||||
ImGui::OpenPopup("slider_menu_popup");
|
||||
ImGuiWrapper::push_menu_style(m_scale);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_::ImGuiStyleVar_ChildRounding, 4.0f * m_scale);
|
||||
|
||||
auto tick_it = GetSelection() == ssHigher ? m_ticks.ticks.find(TickCode{ GetHigherValue() }) :
|
||||
GetSelection() == ssLower ? m_ticks.ticks.find(TickCode{ GetLowerValue() }) :
|
||||
m_ticks.ticks.end();
|
||||
std::string custom_code;
|
||||
if (tick_it != m_ticks.ticks.end()) {
|
||||
render_edit_menu(*tick_it);
|
||||
if (tick_it->type == CustomGCode::Custom)
|
||||
custom_code = tick_it->extra;
|
||||
}
|
||||
else {
|
||||
render_add_menu();
|
||||
}
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_::ImGuiStyleVar_ChildRounding, 4.0f * m_scale);
|
||||
if (ImGui::BeginPopup("slider_menu_popup")) {
|
||||
ImGui::PopStyleVar(1);
|
||||
ImGuiWrapper::pop_menu_style();
|
||||
|
||||
render_input_custom_gcode(custom_code);
|
||||
render_go_to_layer_dialog();
|
||||
}
|
||||
|
||||
void IMSlider::render_add_menu()
|
||||
{
|
||||
int extruder_num = m_extruder_colors.size();
|
||||
|
||||
if (m_show_menu)
|
||||
ImGui::OpenPopup("slider_add_menu_popup");
|
||||
if (ImGui::BeginPopup("slider_add_menu_popup")) {
|
||||
bool menu_item_enable = m_draw_mode != dmSequentialFffPrint;
|
||||
//if ((m_selection == ssLower && GetLowerValueD() == m_zero_layer_height) || (m_selection == ssHigher && GetHigherValueD() == m_zero_layer_height))
|
||||
//{
|
||||
// if (menu_item_with_icon(_u8L("Jump to Layer").c_str(), "")) {
|
||||
// m_show_go_to_layer_dialog = true;
|
||||
// }
|
||||
//}
|
||||
//else
|
||||
bool hovered = false;
|
||||
{
|
||||
if (menu_item_with_icon(_u8L("Add Pause").c_str(), "", ImVec2(0, 0), 0, false, menu_item_enable)) {
|
||||
if (menu_item_with_icon(_u8L("Add Pause").c_str(), "", ImVec2(0, 0), 0, false, menu_item_enable, &hovered)) {
|
||||
add_code_as_tick(PausePrint);
|
||||
}
|
||||
if (menu_item_with_icon(_u8L("Add Custom G-code").c_str(), "", ImVec2(0, 0), 0, false, menu_item_enable)) {
|
||||
if (hovered) { show_tooltip(_u8L("Insert a pause command at the beginning of this layer.")); }
|
||||
|
||||
|
||||
if (menu_item_with_icon(_u8L("Add Custom G-code").c_str(), "", ImVec2(0, 0), 0, false, menu_item_enable, &hovered)) {
|
||||
m_show_custom_gcode_window = true;
|
||||
}
|
||||
if (hovered) { show_tooltip(_u8L("Insert custom G-code at the beginning of this layer.")); }
|
||||
|
||||
if (!gcode(Template).empty()) {
|
||||
if (menu_item_with_icon(_u8L("Add Custom Template").c_str(), "", ImVec2(0, 0), 0, false, menu_item_enable)) {
|
||||
if (menu_item_with_icon(_u8L("Add Custom Template").c_str(), "", ImVec2(0, 0), 0, false, menu_item_enable, &hovered)) {
|
||||
add_code_as_tick(Template);
|
||||
}
|
||||
if (hovered) { show_tooltip(_u8L("Insert template custom G-code at the beginning of this layer.")); }
|
||||
}
|
||||
|
||||
if (menu_item_with_icon(_u8L("Jump to Layer").c_str(), "")) {
|
||||
m_show_go_to_layer_dialog = true;
|
||||
}
|
||||
|
|
@ -1161,26 +1255,78 @@ void IMSlider::render_menu()
|
|||
|
||||
//BBS render this menu item only when extruder_num > 1
|
||||
if (extruder_num > 1) {
|
||||
if (!m_can_change_color || m_draw_mode == dmSequentialFffPrint || m_is_spiral_vase) {
|
||||
if (!m_can_change_color) {
|
||||
begin_menu(_u8L("Change Filament").c_str(), false);
|
||||
}
|
||||
else if (begin_menu(_u8L("Change Filament").c_str())) {
|
||||
for (int i = 0; i < extruder_num; i++) {
|
||||
std::array<float, 4> rgba = decode_color_to_float_array(m_extruder_colors[i]);
|
||||
ImU32 icon_clr = IM_COL32(rgba[0] * 255.0f, rgba[1] * 255.0f, rgba[2] * 255.0f, rgba[3] * 255.0f);
|
||||
if (menu_item_with_icon((_u8L("Filament ") + std::to_string(i + 1)).c_str(), "", ImVec2(14, 14) * m_scale, icon_clr)) add_code_as_tick(ToolChange, i + 1);
|
||||
if (menu_item_with_icon((_u8L("Filament ") + std::to_string(i + 1)).c_str(), "", ImVec2(14, 14) * m_scale, icon_clr, false, true, &hovered)) add_code_as_tick(ToolChange, i + 1);
|
||||
if (hovered) { show_tooltip(_u8L("Change filament at the beginning of this layer.")); }
|
||||
}
|
||||
end_menu();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::PopStyleVar(1);
|
||||
}
|
||||
|
||||
ImGuiWrapper::pop_menu_style();
|
||||
|
||||
render_input_custom_gcode();
|
||||
render_go_to_layer_dialog();
|
||||
void IMSlider::render_edit_menu(const TickCode& tick)
|
||||
{
|
||||
if (m_show_menu)
|
||||
ImGui::OpenPopup("slider_edit_menu_popup");
|
||||
if (ImGui::BeginPopup("slider_edit_menu_popup")) {
|
||||
switch (tick.type)
|
||||
{
|
||||
case CustomGCode::PausePrint:
|
||||
if (menu_item_with_icon(_u8L("Delete Pause").c_str(), "")) {
|
||||
delete_tick(tick);
|
||||
}
|
||||
break;
|
||||
case CustomGCode::Template:
|
||||
if (!gcode(Template).empty()) {
|
||||
if (menu_item_with_icon(_u8L("Delete Custom Template").c_str(), "")) {
|
||||
delete_tick(tick);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CustomGCode::Custom:
|
||||
if (menu_item_with_icon(_u8L("Edit Custom G-code").c_str(), "")) {
|
||||
m_show_custom_gcode_window = true;
|
||||
}
|
||||
if (menu_item_with_icon(_u8L("Delete Custom G-code").c_str(), "")) {
|
||||
delete_tick(tick);
|
||||
}
|
||||
break;
|
||||
case CustomGCode::ToolChange: {
|
||||
int extruder_num = m_extruder_colors.size();
|
||||
if (extruder_num > 1) {
|
||||
if (!m_can_change_color) {
|
||||
begin_menu(_u8L("Change Filament").c_str(), false);
|
||||
}
|
||||
else if (begin_menu(_u8L("Change Filament").c_str())) {
|
||||
for (int i = 0; i < extruder_num; i++) {
|
||||
std::array<float, 4> rgba = decode_color_to_float_array(m_extruder_colors[i]);
|
||||
ImU32 icon_clr = IM_COL32(rgba[0] * 255.0f, rgba[1] * 255.0f, rgba[2] * 255.0f, rgba[3] * 255.0f);
|
||||
if (menu_item_with_icon((_u8L("Filament ") + std::to_string(i + 1)).c_str(), "", ImVec2(14, 14) * m_scale, icon_clr)) add_code_as_tick(ToolChange, i + 1);
|
||||
}
|
||||
end_menu();
|
||||
}
|
||||
if (menu_item_with_icon(_u8L("Delete Filament Change").c_str(), "")) {
|
||||
delete_tick(tick);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CustomGCode::ColorChange:
|
||||
case CustomGCode::Unknown:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void IMSlider::on_change_color_mode(bool is_dark) {
|
||||
|
|
@ -1314,16 +1460,8 @@ std::string IMSlider::get_label(int tick, LabelType label_type)
|
|||
if (label_type == ltHeightWithLayer) {
|
||||
char buffer[64];
|
||||
size_t layer_number;
|
||||
if (m_values[GetMinValueD()] == m_zero_layer_height) {
|
||||
layer_number = m_is_wipe_tower ? get_layer_number(value, label_type): (m_values.empty() ? value : value);
|
||||
m_values[value] == m_zero_layer_height ?
|
||||
::sprintf(buffer, "%5s\n%5s", _u8L("Start").c_str(), _u8L("G-code").c_str()) :
|
||||
::sprintf(buffer, "%5s\n%5s", std::to_string(layer_number).c_str(), layer_height);
|
||||
}
|
||||
else {
|
||||
layer_number = m_is_wipe_tower ? get_layer_number(value, label_type) + 1 : (m_values.empty() ? value : value + 1);
|
||||
::sprintf(buffer, "%5s\n%5s", std::to_string(layer_number).c_str(), layer_height);
|
||||
}
|
||||
layer_number = m_draw_mode == dmSequentialFffPrint ? (m_values.empty() ? value : value + 1) : m_is_wipe_tower ? get_layer_number(value, label_type) + 1 : (m_values.empty() ? value : value + 1);
|
||||
::sprintf(buffer, "%5s\n%5s", std::to_string(layer_number).c_str(), layer_height);
|
||||
return std::string(buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ enum LabelType
|
|||
ltEstimatedTime,
|
||||
};
|
||||
|
||||
|
||||
class IMSlider
|
||||
{
|
||||
public:
|
||||
|
|
@ -129,20 +128,26 @@ public:
|
|||
float m_scale = 1.0;
|
||||
void set_scale(float scale = 1.0);
|
||||
void on_change_color_mode(bool is_dark);
|
||||
void set_menu_enable(bool enable = true) { m_menu_enable = enable; }
|
||||
|
||||
protected:
|
||||
void add_custom_gcode(std::string custom_gcode);
|
||||
void add_code_as_tick(Type type, int selected_extruder = -1);
|
||||
void do_go_to_layer(size_t layer_number);
|
||||
void delete_tick(const TickCode& tick);
|
||||
void do_go_to_layer(size_t layer_number); //menu
|
||||
void correct_lower_value();
|
||||
void correct_higher_value();
|
||||
bool horizontal_slider(const char* str_id, int* v, int v_min, int v_max, const ImVec2& size, float scale = 1.0);
|
||||
void render_go_to_layer_dialog();
|
||||
void render_input_custom_gcode();
|
||||
void render_go_to_layer_dialog(); //menu
|
||||
void render_input_custom_gcode(std::string custom_gcode = ""); //menu
|
||||
void render_menu();
|
||||
void render_add_menu(); //menu
|
||||
void render_edit_menu(const TickCode& tick); //menu
|
||||
void draw_background_and_groove(const ImRect& bg_rect, const ImRect& groove);
|
||||
void draw_colored_band(const ImRect& groove, const ImRect& slideable_region);
|
||||
void draw_ticks(const ImRect& slideable_region);
|
||||
void show_tooltip(const TickCode& tick); //menu
|
||||
void show_tooltip(const std::string tooltip); //menu
|
||||
bool vertical_slider(const char* str_id, int* higher_value, int* lower_value,
|
||||
std::string& higher_label, std::string& lower_label,
|
||||
int v_min, int v_max, const ImVec2& size,
|
||||
|
|
@ -175,21 +180,14 @@ private:
|
|||
bool m_render_as_disabled{ false };
|
||||
|
||||
SelectedSlider m_selection;
|
||||
bool m_is_left_down = false;
|
||||
bool m_is_right_down = false;
|
||||
bool m_is_one_layer = false;
|
||||
bool m_is_focused = false;
|
||||
bool m_show_menu = false;
|
||||
bool m_show_custom_gcode_window = false;
|
||||
bool m_show_go_to_layer_dialog = false;
|
||||
bool m_menu_enable = true; //menu
|
||||
bool m_show_menu = false; //menu
|
||||
bool m_show_custom_gcode_window = false; //menu
|
||||
bool m_show_go_to_layer_dialog = false; //menu
|
||||
bool m_force_mode_apply = true;
|
||||
bool m_enable_action_icon = true;
|
||||
bool m_enable_cog_icon = false;
|
||||
bool m_is_wipe_tower = false; // This flag indicates that there is multiple extruder print with wipe tower
|
||||
bool m_is_spiral_vase = false;
|
||||
bool m_display_lower = true;
|
||||
bool m_display_higher = true;
|
||||
int m_selected_tick_value = -1;
|
||||
|
||||
/* BBS slider images */
|
||||
void *m_one_layer_on_id;
|
||||
|
|
@ -205,6 +203,7 @@ private:
|
|||
void* m_one_layer_off_dark_id;
|
||||
void* m_one_layer_off_hover_dark_id;
|
||||
void *m_pause_icon_id;
|
||||
void *m_custom_icon_id;
|
||||
void *m_delete_icon_id;
|
||||
|
||||
DrawMode m_draw_mode = dmRegular;
|
||||
|
|
@ -228,8 +227,8 @@ private:
|
|||
|
||||
std::vector<double> m_alternate_values;
|
||||
|
||||
char m_custom_gcode[1024] = { 0 };
|
||||
char m_layer_number[64] = { 0 };
|
||||
char m_custom_gcode[1024] = { 0 }; //menu
|
||||
char m_layer_number[64] = { 0 }; //menu
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,10 @@ static const std::map<const wchar_t, std::string> font_icons = {
|
|||
|
||||
{ImGui::TextSearchIcon , "im_text_search" },
|
||||
{ImGui::TextSearchCloseIcon , "im_text_search_close" },
|
||||
|
||||
{ImGui::ExpandBtn , "expand_btn" },
|
||||
{ImGui::CollapseBtn , "collapse_btn" },
|
||||
{ImGui::RevertBtn , "revert_btn" },
|
||||
};
|
||||
static const std::map<const wchar_t, std::string> font_icons_large = {
|
||||
{ImGui::CloseNotifButton , "notification_close" },
|
||||
|
|
@ -120,7 +124,7 @@ const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.333f, 0.333f, 0.333f, 1.0
|
|||
const ImVec4 ImGuiWrapper::COL_GREY_LIGHT = { 0.4f, 0.4f, 0.4f, 1.0f };
|
||||
const ImVec4 ImGuiWrapper::COL_ORANGE_DARK = { 0.757f, 0.404f, 0.216f, 1.0f };
|
||||
const ImVec4 ImGuiWrapper::COL_ORANGE_LIGHT = { 1.0f, 0.49f, 0.216f, 1.0f };
|
||||
const ImVec4 ImGuiWrapper::COL_WINDOW_BACKGROUND = { 0.133f, 0.133f, 0.133f, 0.8f };
|
||||
const ImVec4 ImGuiWrapper::COL_WINDOW_BACKGROUND = { 0.1f, 0.1f, 0.1f, 0.8f };
|
||||
const ImVec4 ImGuiWrapper::COL_BUTTON_BACKGROUND = COL_ORANGE_DARK;
|
||||
const ImVec4 ImGuiWrapper::COL_BUTTON_HOVERED = COL_ORANGE_LIGHT;
|
||||
const ImVec4 ImGuiWrapper::COL_BUTTON_ACTIVE = ImGuiWrapper::COL_BUTTON_HOVERED;
|
||||
|
|
@ -1115,7 +1119,7 @@ bool ImGuiWrapper::undo_redo_list(const ImVec2& size, const bool is_undo, bool (
|
|||
// To do that we push a ColorMarkerHovered symbol at the very beginning of the label
|
||||
// This symbol will be used to a color selection for the highlighted letters.
|
||||
// see imgui_draw.cpp, void ImFont::RenderText()
|
||||
static bool selectable(const char* label, bool selected, ImGuiSelectableFlags flags = 0, const ImVec2& size_arg = ImVec2(0, 0))
|
||||
static bool selectable(const char* label, bool selected, ImGuiSelectableFlags flags = 0, const ImVec2& size_arg = ImVec2(0, 0), bool* out_hovered = nullptr)
|
||||
{
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
|
|
@ -1261,10 +1265,11 @@ static bool selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
|||
if (flags & ImGuiSelectableFlags_Disabled) ImGui::PopStyleColor();
|
||||
if (hovered || selected) ImGui::PopStyleColor();
|
||||
|
||||
if (out_hovered) *out_hovered = hovered;
|
||||
|
||||
// Automatically close popups
|
||||
if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.CurrentItemFlags & ImGuiItemFlags_SelectableDontClosePopup))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
||||
return pressed;
|
||||
}
|
||||
|
|
@ -1433,7 +1438,7 @@ void end_menu()
|
|||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_size /* = ImVec2(0, 0)*/, ImU32 icon_color /* = 0*/, bool selected /* = false*/, bool enabled /* = true*/)
|
||||
bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_size /* = ImVec2(0, 0)*/, ImU32 icon_color /* = 0*/, bool selected /* = false*/, bool enabled /* = true*/, bool* hovered/* = nullptr*/)
|
||||
{
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems) return false;
|
||||
|
|
@ -1466,7 +1471,7 @@ bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_si
|
|||
float shortcut_w = shortcut ? ImGui::CalcTextSize(shortcut, NULL).x : 0.0f;
|
||||
float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame
|
||||
float extra_w = std::max(0.0f, ImGui::GetContentRegionAvail().x - min_w);
|
||||
pressed = selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
|
||||
pressed = selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f), hovered);
|
||||
|
||||
if (icon_size.x != 0 && icon_size.y != 0) {
|
||||
float selectable_pos_y = pos.y + -0.5f * style.ItemSpacing.y;
|
||||
|
|
@ -1665,7 +1670,24 @@ void ImGuiWrapper::bold_text(const std::string& str)
|
|||
text(str);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::push_bold_font() {
|
||||
if (bold_font) {
|
||||
ImGui::PushFont(bold_font);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool ImGuiWrapper::pop_bold_font() {
|
||||
if (bold_font) {
|
||||
ImGui::PopFont();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool ImGuiWrapper::push_font_by_name(std::string font_name)
|
||||
{
|
||||
auto sys_font = im_fonts_map.find(font_name);
|
||||
|
|
@ -2002,6 +2024,37 @@ void ImGuiWrapper::pop_button_disable_style() {
|
|||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
|
||||
void ImGuiWrapper::push_combo_style(const float scale)
|
||||
{
|
||||
if (m_is_dark_mode) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0f * scale);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * scale);
|
||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BG_DARK);
|
||||
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 0.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImGuiWrapper::COL_WINDOW_BG_DARK);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, {1.00f, 1.00f, 1.00f, 0.0f});
|
||||
} else {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0f * scale);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * scale);
|
||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BG);
|
||||
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 0.5f));
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImGuiWrapper::COL_WINDOW_BG);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, {1.00f, 1.00f, 1.00f, 0.0f});
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiWrapper::pop_combo_style()
|
||||
{
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::PopStyleColor(7);
|
||||
}
|
||||
|
||||
void ImGuiWrapper::init_font(bool compress)
|
||||
{
|
||||
destroy_font();
|
||||
|
|
@ -2026,7 +2079,7 @@ void ImGuiWrapper::init_font(bool compress)
|
|||
cfg.OversampleH = cfg.OversampleV = 1;
|
||||
//FIXME replace with io.Fonts->AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, m_font_size, nullptr, ranges.Data);
|
||||
//https://github.com/ocornut/imgui/issues/220
|
||||
default_font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + "HarmonyOS_Sans_SC_Regular.ttf").c_str(), m_font_size, &cfg, ImGui::GetIO().Fonts->GetGlyphRangesChineseFull());
|
||||
default_font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + "HarmonyOS_Sans_SC_Regular.ttf").c_str(), m_font_size, &cfg, m_font_cjk ? ImGui::GetIO().Fonts->GetGlyphRangesChineseFull() : ranges.Data);
|
||||
if (default_font == nullptr) {
|
||||
default_font = io.Fonts->AddFontDefault();
|
||||
if (default_font == nullptr) {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ bool button_with_pos(ImTextureID user_texture_id,
|
|||
const ImVec2 &margin = ImVec2(0, 0));
|
||||
bool begin_menu(const char *label, bool enabled = true);
|
||||
void end_menu();
|
||||
bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_size = ImVec2(0, 0), ImU32 icon_color = 0, bool selected = false, bool enabled = true);
|
||||
bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_size = ImVec2(0, 0), ImU32 icon_color = 0, bool selected = false, bool enabled = true, bool* hovered = nullptr);
|
||||
|
||||
|
||||
class ImGuiWrapper
|
||||
|
|
@ -160,6 +160,8 @@ public:
|
|||
|
||||
// set font
|
||||
const std::vector<std::string> get_fonts_names() const { return m_fonts_names; }
|
||||
bool push_bold_font();
|
||||
bool pop_bold_font();
|
||||
bool push_font_by_name(std::string font_name);
|
||||
bool pop_font_by_name(std::string font_name);
|
||||
void load_fonts_texture();
|
||||
|
|
@ -213,6 +215,8 @@ public:
|
|||
static void pop_cancel_button_style();
|
||||
static void push_button_disable_style();
|
||||
static void pop_button_disable_style();
|
||||
static void push_combo_style(const float scale);
|
||||
static void pop_combo_style();
|
||||
|
||||
//BBS
|
||||
static int TOOLBAR_WINDOW_FLAGS;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "I18N.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
|
|
@ -68,6 +69,7 @@ void ImageGrid::SetFileSystem(boost::shared_ptr<PrinterFileSystem> file_sys)
|
|||
m_row_count = 0;
|
||||
m_col_count = 1;
|
||||
m_row_offset = 0;
|
||||
m_scroll_offset = 0;
|
||||
UpdateFileSystem();
|
||||
}
|
||||
|
||||
|
|
@ -102,6 +104,7 @@ void Slic3r::GUI::ImageGrid::SetGroupMode(int mode)
|
|||
m_row_offset = index / m_col_count * 4;
|
||||
if (m_row_offset >= m_row_count)
|
||||
m_row_offset = m_row_count == 0 ? 0 : m_row_count - 1;
|
||||
m_scroll_offset = 0;
|
||||
}
|
||||
|
||||
void Slic3r::GUI::ImageGrid::SetSelecting(bool selecting)
|
||||
|
|
@ -127,11 +130,12 @@ void Slic3r::GUI::ImageGrid::Rescale()
|
|||
|
||||
void Slic3r::GUI::ImageGrid::Select(size_t index)
|
||||
{
|
||||
if (m_selecting) {
|
||||
m_file_sys->ToggleSelect(index);
|
||||
Refresh();
|
||||
return;
|
||||
}
|
||||
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
|
||||
if (m_selecting) {
|
||||
m_file_sys->ToggleSelect(index);
|
||||
Refresh();
|
||||
}
|
||||
return;
|
||||
}
|
||||
index = m_file_sys->EnterSubGroup(index);
|
||||
|
|
@ -139,12 +143,20 @@ void Slic3r::GUI::ImageGrid::Select(size_t index)
|
|||
m_row_offset = index / m_col_count * 4;
|
||||
if (m_row_offset >= m_row_count)
|
||||
m_row_offset = m_row_count == 0 ? 0 : m_row_count - 1;
|
||||
m_scroll_offset = 0;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Slic3r::GUI::ImageGrid::DoAction(size_t index, int action)
|
||||
{
|
||||
if (action == 0) {
|
||||
if (m_file_sys->GetSelectCount() > 1) {
|
||||
MessageDialog dlg(this,
|
||||
wxString::Format(_L("You are going to delete %u files. Are you sure to continue?"), m_file_sys->GetSelectCount()),
|
||||
_L("Delete files"), wxYES_NO | wxICON_WARNING);
|
||||
if (dlg.ShowModal() != wxID_YES)
|
||||
return;
|
||||
}
|
||||
m_file_sys->DeleteFiles(index);
|
||||
} else if (action == 1) {
|
||||
if (index != -1) {
|
||||
|
|
@ -152,7 +164,9 @@ void Slic3r::GUI::ImageGrid::DoAction(size_t index, int action)
|
|||
if (file.IsDownload() && file.progress >= -1) {
|
||||
if (file.progress >= 100) {
|
||||
if (!m_file_sys->DownloadCheckFile(index)) {
|
||||
wxMessageBox(wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)), _L("Error"), wxOK);
|
||||
MessageDialog(this,
|
||||
wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)),
|
||||
_L("Error"), wxOK).ShowModal();
|
||||
Refresh();
|
||||
return;
|
||||
}
|
||||
|
|
@ -176,7 +190,9 @@ void Slic3r::GUI::ImageGrid::DoAction(size_t index, int action)
|
|||
if (file.IsDownload() && file.progress >= -1) {
|
||||
if (file.progress >= 100) {
|
||||
if (!m_file_sys->DownloadCheckFile(index)) {
|
||||
wxMessageBox(wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)), _L("Error"), wxOK);
|
||||
MessageDialog(this,
|
||||
wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)),
|
||||
_L("Error"), wxOK).ShowModal();
|
||||
Refresh();
|
||||
return;
|
||||
}
|
||||
|
|
@ -231,6 +247,7 @@ void ImageGrid::UpdateLayout()
|
|||
m_row_count = nrow > 0 ? nrow + 1 : 0;
|
||||
if (m_row_offset >= m_row_count)
|
||||
m_row_offset = m_row_count == 0 ? 0 : m_row_count - 1;
|
||||
m_scroll_offset = 0;
|
||||
// create mask
|
||||
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
|
||||
mask_size.x = (m_col_count - 1) * m_cell_size.GetWidth() + m_image_size.GetWidth();
|
||||
|
|
@ -369,13 +386,14 @@ void ImageGrid::resize(wxSizeEvent& event)
|
|||
void ImageGrid::mouseWheelMoved(wxMouseEvent &event)
|
||||
{
|
||||
auto delta = -event.GetWheelRotation();
|
||||
m_scroll_offset += delta;
|
||||
int max = m_row_count * m_cell_size.GetHeight() / 4;
|
||||
if (m_scroll_offset < 0)
|
||||
m_scroll_offset = 0;
|
||||
else if (m_scroll_offset >= max)
|
||||
m_scroll_offset = max - 1;
|
||||
m_row_offset = m_scroll_offset * 4 / m_cell_size.GetHeight();
|
||||
m_scroll_offset += delta * 4;
|
||||
delta = m_scroll_offset / m_cell_size.GetHeight();
|
||||
m_row_offset += delta;
|
||||
if (m_row_offset < 0)
|
||||
m_row_offset = 0;
|
||||
else if (m_row_offset >= m_row_count)
|
||||
m_row_offset = m_row_count == 0 ? 0 : m_row_count - 1;
|
||||
m_scroll_offset -= delta * m_cell_size.GetHeight();
|
||||
m_timer.StartOnce(4000); // Show position bar
|
||||
UpdateFocusRange();
|
||||
Refresh();
|
||||
|
|
@ -465,6 +483,8 @@ wxBitmap Slic3r::GUI::ImageGrid::createCircleBitmap(wxSize size, int borderWidth
|
|||
return bmp;
|
||||
}
|
||||
|
||||
static constexpr wchar_t const *TIME_FORMATS[] = {_T("%Y-%m-%d"), _T("%Y-%m"), _T("%Y")};
|
||||
|
||||
/*
|
||||
* Here we do the actual rendering. I put it in a separate
|
||||
* method so that it can work no matter what type of DC
|
||||
|
|
@ -495,7 +515,6 @@ void ImageGrid::render(wxDC& dc)
|
|||
// Draw line spacing at top
|
||||
if (off.y > 0)
|
||||
dc.DrawRectangle({0, 0, size.x, off.y});
|
||||
constexpr wchar_t const * formats[] = {_T("%Y-%m-%d"), _T("%Y-%m"), _T("%Y")};
|
||||
size_t start = index;
|
||||
size_t end = index;
|
||||
size_t hit_image = m_selecting ? size_t(-1) : m_hit_type == HIT_ITEM ? m_hit_item : m_hit_type == HIT_ACTION ? m_hit_item / 4 :size_t(-1);
|
||||
|
|
@ -506,65 +525,7 @@ void ImageGrid::render(wxDC& dc)
|
|||
wxPoint pt{off.x, off.y};
|
||||
end = (index + m_col_count) < m_file_sys->GetCount() ? index + m_col_count : m_file_sys->GetCount();
|
||||
while (index < end) {
|
||||
auto & file = m_file_sys->GetFile(index);
|
||||
// Draw thumbnail
|
||||
if (file.thumbnail.IsOk()) {
|
||||
float hs = (float) m_image_size.GetWidth() / file.thumbnail.GetWidth();
|
||||
float vs = (float) m_image_size.GetHeight() / file.thumbnail.GetHeight();
|
||||
dc.SetUserScale(hs, vs);
|
||||
dc.DrawBitmap(file.thumbnail, {(int) (pt.x / hs), (int) (pt.y / vs)});
|
||||
dc.SetUserScale(1, 1);
|
||||
if (m_file_sys->GetGroupMode() != PrinterFileSystem::G_NONE) {
|
||||
dc.DrawBitmap(m_mask, pt);
|
||||
}
|
||||
}
|
||||
bool show_download_state_always = true;
|
||||
// Draw checked icon
|
||||
if (m_selecting && !show_download_state_always)
|
||||
dc.DrawBitmap(file.IsSelect() ? m_checked_icon.bmp() : m_unchecked_icon.bmp(),
|
||||
pt + wxPoint{10, m_image_size.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
|
||||
// can't handle alpha
|
||||
// dc.GradientFillLinear({pt.x, pt.y, m_image_size.GetWidth(), 60}, wxColour(0x6F, 0x6F, 0x6F, 0x99), wxColour(0x6F, 0x6F, 0x6F, 0), wxBOTTOM);
|
||||
else if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
|
||||
wxString nonHoverText;
|
||||
wxString secondAction = _L("Download");
|
||||
wxString thirdAction;
|
||||
int states = 0;
|
||||
// Draw download progress
|
||||
if (file.IsDownload()) {
|
||||
if (file.progress == -1) {
|
||||
secondAction = _L("Cancel");
|
||||
nonHoverText = _L("Download waiting...");
|
||||
} else if (file.progress < 0) {
|
||||
secondAction = _L("Retry");
|
||||
nonHoverText = _L("Download failed");
|
||||
states = StateColor::Checked;
|
||||
} else if (file.progress >= 100) {
|
||||
secondAction = _L("Play");
|
||||
thirdAction = _L("Open Folder");
|
||||
nonHoverText = _L("Download finished");
|
||||
} else {
|
||||
secondAction = _L("Cancel");
|
||||
nonHoverText = wxString::Format(_L("Downloading %d%%..."), file.progress);
|
||||
thirdAction = wxString::Format(L"%d%%...", file.progress);
|
||||
}
|
||||
}
|
||||
// Draw buttons on hovered item
|
||||
wxRect rect{pt.x, pt.y + m_image_size.y - m_buttons_background.GetHeight(), m_image_size.GetWidth(), m_buttons_background.GetHeight()};
|
||||
if (hit_image == index) {
|
||||
renderButtons(dc, {_L("Delete"), (wxChar const *) secondAction, thirdAction.IsEmpty() ? nullptr : (wxChar const *) thirdAction, nullptr}, rect,
|
||||
m_hit_type == HIT_ACTION ? m_hit_item & 3 : -1, states);
|
||||
} else if (!nonHoverText.IsEmpty()) {
|
||||
renderButtons(dc, {(wxChar const *) nonHoverText, nullptr}, rect, -1, states);
|
||||
}
|
||||
if (m_selecting && show_download_state_always)
|
||||
dc.DrawBitmap(file.IsSelect() ? m_checked_icon.bmp() : m_unchecked_icon.bmp(),
|
||||
pt + wxPoint{10, m_image_size.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
|
||||
} else {
|
||||
dc.SetTextForeground(*wxWHITE); // time text color
|
||||
auto date = wxDateTime((time_t) file.time).Format(_L(formats[m_file_sys->GetGroupMode()]));
|
||||
dc.DrawText(date, pt + wxPoint{24, 16});
|
||||
}
|
||||
renderContent(dc, pt, index, hit_image == index);
|
||||
// Draw colume spacing at right
|
||||
dc.DrawRectangle({pt.x + m_image_size.GetWidth(), pt.y, m_cell_size.GetWidth() - m_image_size.GetWidth(), m_image_size.GetHeight()});
|
||||
++index;
|
||||
|
|
@ -583,8 +544,8 @@ void ImageGrid::render(wxDC& dc)
|
|||
dc.DrawRectangle({off.x, 0}, m_mask.GetSize());
|
||||
auto & file1 = m_file_sys->GetFile(start);
|
||||
auto & file2 = m_file_sys->GetFile(end - 1);
|
||||
auto date1 = wxDateTime((time_t) file1.time).Format(_L(formats[m_file_sys->GetGroupMode()]));
|
||||
auto date2 = wxDateTime((time_t) file2.time).Format(_L(formats[m_file_sys->GetGroupMode()]));
|
||||
auto date1 = wxDateTime((time_t) file1.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
|
||||
auto date2 = wxDateTime((time_t) file2.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
|
||||
dc.SetFont(Label::Head_16);
|
||||
dc.SetTextForeground(StateColor::darkModeColorFor("#262E30"));
|
||||
dc.DrawText(date1 + " - " + date2, wxPoint{off.x, 2});
|
||||
|
|
@ -605,6 +566,68 @@ void ImageGrid::render(wxDC& dc)
|
|||
}
|
||||
}
|
||||
|
||||
void Slic3r::GUI::ImageGrid::renderContent(wxDC &dc, wxPoint const &pt, int index, bool hit)
|
||||
{
|
||||
bool selected = false;
|
||||
auto &file = m_file_sys->GetFile(index, selected);
|
||||
// Draw thumbnail
|
||||
if (file.thumbnail.IsOk()) {
|
||||
float hs = (float) m_image_size.GetWidth() / file.thumbnail.GetWidth();
|
||||
float vs = (float) m_image_size.GetHeight() / file.thumbnail.GetHeight();
|
||||
dc.SetUserScale(hs, vs);
|
||||
dc.DrawBitmap(file.thumbnail, {(int) (pt.x / hs), (int) (pt.y / vs)});
|
||||
dc.SetUserScale(1, 1);
|
||||
if (m_file_sys->GetGroupMode() != PrinterFileSystem::G_NONE) {
|
||||
dc.DrawBitmap(m_mask, pt);
|
||||
}
|
||||
}
|
||||
bool show_download_state_always = true;
|
||||
// Draw checked icon
|
||||
if (m_selecting && !show_download_state_always)
|
||||
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, m_image_size.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
|
||||
// can't handle alpha
|
||||
// dc.GradientFillLinear({pt.x, pt.y, m_border_size.GetWidth(), 60}, wxColour(0x6F, 0x6F, 0x6F, 0x99), wxColour(0x6F, 0x6F, 0x6F, 0), wxBOTTOM);
|
||||
else if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
|
||||
wxString nonHoverText;
|
||||
wxString secondAction = _L("Download");
|
||||
wxString thirdAction;
|
||||
int states = 0;
|
||||
// Draw download progress
|
||||
if (file.IsDownload()) {
|
||||
if (file.progress == -1) {
|
||||
secondAction = _L("Cancel");
|
||||
nonHoverText = _L("Download waiting...");
|
||||
} else if (file.progress < 0) {
|
||||
secondAction = _L("Retry");
|
||||
nonHoverText = _L("Download failed");
|
||||
states = StateColor::Checked;
|
||||
} else if (file.progress >= 100) {
|
||||
secondAction = _L("Play");
|
||||
thirdAction = _L("Open Folder");
|
||||
nonHoverText = _L("Download finished");
|
||||
} else {
|
||||
secondAction = _L("Cancel");
|
||||
nonHoverText = wxString::Format(_L("Downloading %d%%..."), file.progress);
|
||||
thirdAction = wxString::Format(L"%d%%...", file.progress);
|
||||
}
|
||||
}
|
||||
// Draw buttons on hovered item
|
||||
wxRect rect{pt.x, pt.y + m_image_size.GetHeight() - m_buttons_background.GetHeight(), m_image_size.GetWidth(), m_buttons_background.GetHeight()};
|
||||
if (hit) {
|
||||
renderButtons(dc, {_L("Delete"), (wxChar const *) secondAction, thirdAction.IsEmpty() ? nullptr : (wxChar const *) thirdAction, nullptr}, rect,
|
||||
m_hit_type == HIT_ACTION ? m_hit_item & 3 : -1, states);
|
||||
} else if (!nonHoverText.IsEmpty()) {
|
||||
renderButtons(dc, {(wxChar const *) nonHoverText, nullptr}, rect, -1, states);
|
||||
}
|
||||
} else {
|
||||
dc.SetTextForeground(*wxWHITE); // time text color
|
||||
auto date = wxDateTime((time_t) file.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
|
||||
dc.DrawText(date, pt + wxPoint{24, 16});
|
||||
}
|
||||
if (m_selecting && show_download_state_always)
|
||||
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, m_image_size.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
|
||||
}
|
||||
|
||||
void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxStringList const &texts, wxRect const &rect2, size_t hit, int states)
|
||||
{
|
||||
// Draw background
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ protected:
|
|||
|
||||
void render(wxDC &dc);
|
||||
|
||||
void renderContent(wxDC &dc, wxPoint const &pt, int index, bool hit);
|
||||
|
||||
void renderButtons(wxDC &dc, wxStringList const &texts, wxRect const &rect, size_t hit, int states);
|
||||
|
||||
void renderText(wxDC &dc, wxString const & text, wxRect const & rect, int states);
|
||||
|
|
|
|||
|
|
@ -241,9 +241,15 @@ void ArrangeJob::prepare_all() {
|
|||
}
|
||||
|
||||
// 准备料塔。逻辑如下:
|
||||
// 1. 如果料塔被禁用,或是逐件打印,则不需要料塔
|
||||
// 2. 以下两种情况需要料塔:1)某对象是多色对象;2)打开了支撑,且支撑体与接触面使用的是不同材料
|
||||
// 3. 如果允许不同材料落在相同盘,则以下情况也需要料塔:1)所有选定对象中使用了多种热床温度相同的材料(比如颜色不同的PLA)
|
||||
// 1. 以下几种情况不需要料塔:
|
||||
// 1)料塔被禁用,
|
||||
// 2)逐件打印,
|
||||
// 3)不允许不同材料落在相同盘,且没有多色对象
|
||||
// 2. 以下情况需要料塔:
|
||||
// 1)某对象是多色对象;
|
||||
// 2)打开了支撑,且支撑体与接触面使用的是不同材料
|
||||
// 3)允许不同材料落在相同盘,且所有选定对象中使用了多种热床温度相同的材料
|
||||
// (所有对象都是单色的,但不同对象的材料不同,例如:对象A使用红色PLA,对象B使用白色PLA)
|
||||
void ArrangeJob::prepare_wipe_tower()
|
||||
{
|
||||
bool need_wipe_tower = false;
|
||||
|
|
@ -257,7 +263,7 @@ void ArrangeJob::prepare_wipe_tower()
|
|||
// need wipe tower if some object has multiple extruders (has paint-on colors or support material)
|
||||
for (const auto &item : m_selected) {
|
||||
std::set<int> obj_extruders;
|
||||
for (int id : item.extrude_ids) obj_extruders.insert(id);
|
||||
obj_extruders.insert(item.extrude_ids.begin(), item.extrude_ids.end());
|
||||
if (obj_extruders.size() > 1) {
|
||||
need_wipe_tower = true;
|
||||
BOOST_LOG_TRIVIAL(info) << "arrange: need wipe tower because object " << item.name << " has multiple extruders (has paint-on colors)";
|
||||
|
|
@ -266,6 +272,7 @@ void ArrangeJob::prepare_wipe_tower()
|
|||
}
|
||||
|
||||
// if multile extruders have same bed temp, we need wipe tower
|
||||
// 允许不同材料落在相同盘,且所有选定对象中使用了多种热床温度相同的材料
|
||||
if (params.allow_multi_materials_on_same_plate) {
|
||||
std::map<int, std::set<int>> bedTemp2extruderIds;
|
||||
for (const auto &item : m_selected)
|
||||
|
|
@ -294,17 +301,19 @@ void ArrangeJob::prepare_wipe_tower()
|
|||
}
|
||||
|
||||
// if wipe tower is not init yet (no wipe tower in any plate before arrangement)
|
||||
if (wipe_tower_ap.poly.empty()) {
|
||||
auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||
wipe_tower_ap.poly.contour.points = print.first_layer_wipe_tower_corners(false);
|
||||
//if (wipe_tower_ap.poly.empty()) {
|
||||
// auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||
// wipe_tower_ap.poly.contour.points = print.first_layer_wipe_tower_corners(false);
|
||||
wipe_tower_ap.name = "WipeTower";
|
||||
wipe_tower_ap.is_virt_object = true;
|
||||
wipe_tower_ap.is_wipe_tower = true;
|
||||
}
|
||||
|
||||
//}
|
||||
const GLCanvas3D* canvas3D=static_cast<const GLCanvas3D *>(m_plater->canvas3D());
|
||||
for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) {
|
||||
if (!plates_have_wipe_tower[bedid]) {
|
||||
wipe_tower_ap.bed_idx = bedid;
|
||||
wipe_tower_ap.translation = {0, 0};
|
||||
wipe_tower_ap.poly.contour.points = canvas3D->estimate_wipe_tower_points(bedid, !only_on_partplate);
|
||||
wipe_tower_ap.bed_idx = bedid;
|
||||
m_unselected.emplace_back(wipe_tower_ap);
|
||||
}
|
||||
}
|
||||
|
|
@ -502,7 +511,7 @@ void ArrangeJob::process()
|
|||
auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||
|
||||
if (params.is_seq_print)
|
||||
params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius));
|
||||
params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error
|
||||
|
||||
if (params.avoid_extrusion_cali_region && print.full_print_config().opt_bool("scan_first_layer"))
|
||||
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
|
||||
|
|
@ -750,6 +759,7 @@ void ArrangeJob::finalize() {
|
|||
m_plater->update();
|
||||
|
||||
Job::finalize();
|
||||
m_plater->m_arrange_running.store(false);
|
||||
}
|
||||
|
||||
std::optional<arrangement::ArrangePolygon>
|
||||
|
|
|
|||
|
|
@ -32,10 +32,11 @@ wxString get_login_fail_reason(std::string fail_reason)
|
|||
return _L("Unknown Failure");
|
||||
}
|
||||
|
||||
BindJob::BindJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater, std::string dev_id, std::string dev_ip)
|
||||
BindJob::BindJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater, std::string dev_id, std::string dev_ip, std::string sec_link)
|
||||
: PlaterJob{std::move(pri), plater},
|
||||
m_dev_id(dev_id),
|
||||
m_dev_ip(dev_ip)
|
||||
m_dev_ip(dev_ip),
|
||||
m_sec_link(sec_link)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
|
@ -79,7 +80,7 @@ void BindJob::process()
|
|||
long offset = tz.GetOffset();
|
||||
std::string timezone = get_timezone_utc_hm(offset);
|
||||
|
||||
int result = m_agent->bind(m_dev_ip, timezone,
|
||||
int result = m_agent->bind(m_dev_ip, m_dev_id, m_sec_link, timezone,
|
||||
[this, &curr_percent, &msg](int stage, int code, std::string info) {
|
||||
if (stage == BBL::BindJobStage::LoginStageConnect) {
|
||||
curr_percent = 15;
|
||||
|
|
|
|||
|
|
@ -16,13 +16,14 @@ class BindJob : public PlaterJob
|
|||
std::function<void()> m_success_fun{nullptr};
|
||||
std::string m_dev_id;
|
||||
std::string m_dev_ip;
|
||||
std::string m_sec_link;
|
||||
bool m_job_finished{ false };
|
||||
int m_print_job_completed_id = 0;
|
||||
|
||||
protected:
|
||||
void on_exception(const std::exception_ptr &) override;
|
||||
public:
|
||||
BindJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater, std::string dev_id, std::string dev_ip);
|
||||
BindJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater, std::string dev_id, std::string dev_ip, std::string sec_link);
|
||||
|
||||
int status_range() const override
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ void GUI::Job::update_percent_finish()
|
|||
m_progress->clear_percent();
|
||||
}
|
||||
|
||||
void GUI::Job::show_networking_test(wxString msg)
|
||||
{
|
||||
m_progress->show_networking_test(msg);
|
||||
}
|
||||
|
||||
GUI::Job::Job(std::shared_ptr<ProgressIndicator> pri)
|
||||
: m_progress(std::move(pri))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ protected:
|
|||
|
||||
void update_percent_finish();
|
||||
|
||||
void show_networking_test(wxString msg);
|
||||
|
||||
bool was_canceled() const { return m_canceled.load(); }
|
||||
|
||||
// Launched just before start(), a job can use it to prepare internals
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ void NotificationProgressIndicator::clear_percent()
|
|||
|
||||
}
|
||||
|
||||
void NotificationProgressIndicator::show_networking_test(wxString msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void NotificationProgressIndicator::set_range(int range)
|
||||
{
|
||||
m_nm->progress_indicator_set_range(range);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ public:
|
|||
explicit NotificationProgressIndicator(NotificationManager *nm);
|
||||
|
||||
void clear_percent() override;
|
||||
void show_networking_test(wxString msg) override;
|
||||
void set_range(int range) override;
|
||||
void set_cancel_callback(CancelFn = CancelFn()) override;
|
||||
void set_progress(int pr) override;
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ void PrintJob::process()
|
|||
{
|
||||
/* display info */
|
||||
wxString msg;
|
||||
wxString error_str;
|
||||
int curr_percent = 10;
|
||||
NetworkAgent* m_agent = wxGetApp().getAgent();
|
||||
AppConfig* config = wxGetApp().app_config;
|
||||
|
|
@ -157,6 +158,10 @@ void PrintJob::process()
|
|||
else
|
||||
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
|
||||
|
||||
PartPlate* curr_plate = m_plater->get_partplate_list().get_curr_plate();
|
||||
if (curr_plate) {
|
||||
this->task_bed_type = bed_type_to_gcode_string(curr_plate->get_bed_type(true));
|
||||
}
|
||||
|
||||
BBL::PrintParams params;
|
||||
|
||||
|
|
@ -200,6 +205,7 @@ void PrintJob::process()
|
|||
params.ams_mapping_info = this->task_ams_mapping_info;
|
||||
params.connection_type = this->connection_type;
|
||||
params.task_use_ams = this->task_use_ams;
|
||||
params.task_bed_type = this->task_bed_type;
|
||||
if (wxGetApp().model().model_info && wxGetApp().model().model_info.get()) {
|
||||
ModelInfo* model_info = wxGetApp().model().model_info.get();
|
||||
auto origin_profile_id = model_info->metadata_items.find(BBL_DESIGNER_PROFILE_ID_TAG);
|
||||
|
|
@ -227,19 +233,22 @@ void PrintJob::process()
|
|||
30, // PrintingStageUpload
|
||||
70, // PrintingStageWaiting
|
||||
75, // PrintingStageRecord
|
||||
99, // PrintingStageSending
|
||||
97, // PrintingStageSending
|
||||
100 // PrintingStageFinished
|
||||
};
|
||||
|
||||
auto update_fn = [this, &msg, &curr_percent, &error_text, StagePercentPoint](int stage, int code, std::string info) {
|
||||
if (stage == BBL::SendingPrintJobStage::PrintingStageCreate) {
|
||||
bool is_try_lan_mode = false;
|
||||
bool is_try_lan_mode_failed = false;
|
||||
|
||||
auto update_fn = [this, &is_try_lan_mode, &is_try_lan_mode_failed, &msg, &error_str, &curr_percent, &error_text, StagePercentPoint](int stage, int code, std::string info) {
|
||||
if (stage == BBL::SendingPrintJobStage::PrintingStageCreate && !is_try_lan_mode_failed) {
|
||||
if (this->connection_type == "lan") {
|
||||
msg = _L("Sending print job over LAN");
|
||||
} else {
|
||||
msg = _L("Sending print job through cloud service");
|
||||
}
|
||||
}
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageUpload) {
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageUpload && !is_try_lan_mode_failed) {
|
||||
if (code >= 0 && code <= 100 && !info.empty()) {
|
||||
if (this->connection_type == "lan") {
|
||||
msg = _L("Sending print job over LAN");
|
||||
|
|
@ -256,10 +265,10 @@ void PrintJob::process()
|
|||
msg = _L("Sending print job through cloud service");
|
||||
}
|
||||
}
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageRecord) {
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageRecord && !is_try_lan_mode) {
|
||||
msg = _L("Sending print configuration");
|
||||
}
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageSending) {
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageSending && !is_try_lan_mode) {
|
||||
if (this->connection_type == "lan") {
|
||||
msg = _L("Sending print job over LAN");
|
||||
} else {
|
||||
|
|
@ -289,9 +298,11 @@ void PrintJob::process()
|
|||
|
||||
if (code > 100 || code < 0) {
|
||||
error_text = this->get_http_error_msg(code, info);
|
||||
msg += wxString::Format("[%s]", error_text);
|
||||
error_str = wxString::Format("[%s]", error_text);
|
||||
} else {
|
||||
error_str = wxEmptyString;
|
||||
}
|
||||
this->update_status(curr_percent, msg);
|
||||
this->update_status(curr_percent, msg + error_str);
|
||||
};
|
||||
|
||||
auto cancel_fn = [this]() {
|
||||
|
|
@ -319,6 +330,7 @@ void PrintJob::process()
|
|||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << "print_job: use ftp send print only";
|
||||
this->update_status(curr_percent, _L("Sending print job over LAN"));
|
||||
is_try_lan_mode = true;
|
||||
result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn);
|
||||
if (result < 0) {
|
||||
error_text = wxString::Format("Access code:%s Ip address:%s", params.password, params.dev_ip);
|
||||
|
|
@ -336,7 +348,10 @@ void PrintJob::process()
|
|||
BOOST_LOG_TRIVIAL(info) << "print_job: try to start local print with record";
|
||||
this->update_status(curr_percent, _L("Sending print job over LAN"));
|
||||
result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn);
|
||||
if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
|
||||
if (result == 0) {
|
||||
params.comments = "";
|
||||
}
|
||||
else if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
|
||||
params.comments = "wrong_code";
|
||||
}
|
||||
else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
|
||||
|
|
@ -346,6 +361,7 @@ void PrintJob::process()
|
|||
params.comments = (boost::format("failed(%1%)") % result).str();
|
||||
}
|
||||
if (result < 0) {
|
||||
is_try_lan_mode_failed = true;
|
||||
// try to send with cloud
|
||||
BOOST_LOG_TRIVIAL(warning) << "print_job: try to send with cloud";
|
||||
this->update_status(curr_percent, _L("Sending print job through cloud service"));
|
||||
|
|
@ -384,7 +400,7 @@ void PrintJob::process()
|
|||
} else if (result == BAMBU_NETWORK_ERR_TIMEOUT) {
|
||||
msg_text = timeout_to_upload_str;
|
||||
} else if (result == BAMBU_NETWORK_ERR_INVALID_RESULT) {
|
||||
msg_text = _L("Failed to send the print job. Please try again.");
|
||||
msg_text = _L("Failed to send the print job. Please try again.");
|
||||
} else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
|
||||
msg_text = _L("Failed to send the print job. Please try again.");
|
||||
} else {
|
||||
|
|
@ -394,7 +410,15 @@ void PrintJob::process()
|
|||
curr_percent = 0;
|
||||
msg_text += wxString::Format("[%d][%s]", result, error_text);
|
||||
}
|
||||
update_status(curr_percent, msg_text);
|
||||
|
||||
|
||||
if (result == BAMBU_NETWORK_ERR_INVALID_RESULT) {
|
||||
this->show_networking_test(msg_text);
|
||||
}
|
||||
else {
|
||||
update_status(curr_percent, msg_text);
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(error) << "print_job: failed, result = " << result;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "print_job: send ok.";
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ public:
|
|||
virtual ~ProgressIndicator() = default;
|
||||
|
||||
virtual void clear_percent() = 0;
|
||||
virtual void show_networking_test(wxString msg) = 0;
|
||||
virtual void set_range(int range) = 0;
|
||||
virtual void set_cancel_callback(CancelFn = CancelFn()) = 0;
|
||||
virtual void set_progress(int pr) = 0;
|
||||
|
|
|
|||
|
|
@ -162,9 +162,26 @@ void SendJob::process()
|
|||
|
||||
PartPlate* plate = m_plater->get_partplate_list().get_plate(job_data.plate_idx);
|
||||
if (plate == nullptr) {
|
||||
plate = m_plater->get_partplate_list().get_curr_plate();
|
||||
if (plate == nullptr)
|
||||
return;
|
||||
if (job_data.plate_idx == PLATE_ALL_IDX) {
|
||||
//all plate
|
||||
for (int index = 0; index < total_plate_num; index++)
|
||||
{
|
||||
PartPlate* plate_n = m_plater->get_partplate_list().get_plate(index);
|
||||
if (plate_n && plate_n->is_valid_gcode_file())
|
||||
{
|
||||
plate = plate_n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
plate = m_plater->get_partplate_list().get_curr_plate();
|
||||
}
|
||||
if (plate == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(error) << "can not find plate with valid gcode file when sending to print, plate_index="<< job_data.plate_idx;
|
||||
update_status(curr_percent, check_gcode_failed_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* check gcode is valid */
|
||||
|
|
@ -350,7 +367,7 @@ void SendJob::process()
|
|||
}
|
||||
|
||||
if (result == BAMBU_NETWORK_ERR_WRONG_IP_ADDRESS) {
|
||||
msg_text = _L("Failed uploading print file. Please enter ip address again.");
|
||||
msg_text = timeout_to_upload_str;
|
||||
}
|
||||
|
||||
update_status(curr_percent, msg_text);
|
||||
|
|
|
|||
|
|
@ -183,7 +183,12 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
// Slice plate
|
||||
{ ctrl + "R", L("Slice plate")},
|
||||
// Send to Print
|
||||
{ ctrl + "Shift" + "G", L("Print plate")},
|
||||
#ifdef __APPLE__
|
||||
{ L("⌘+Shift+G"), L("Print plate")},
|
||||
#else
|
||||
{ L("Ctrl+Shift+G"), L("Print plate")},
|
||||
#endif // __APPLE
|
||||
|
||||
// Edit
|
||||
{ ctrl + "X", L("Cut") },
|
||||
{ ctrl + "C", L("Copy to clipboard") },
|
||||
|
|
@ -196,7 +201,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
#ifdef __APPLE__
|
||||
{"fn+⌫", L("Delete selected")},
|
||||
#else
|
||||
{"Del", L("Delete selected")},
|
||||
{L("Del"), L("Delete selected")},
|
||||
#endif
|
||||
// Help
|
||||
{ "?", L("Show keyboard shortcuts list") }
|
||||
|
|
@ -208,12 +213,12 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
{ L("Right mouse button"), L("Pan View") },
|
||||
{ L("Mouse wheel"), L("Zoom View") },
|
||||
{ "A", L("Arrange all objects") },
|
||||
{ "Shift+A", L("Arrange objects on selected plates") },
|
||||
{ L("Shift+A"), L("Arrange objects on selected plates") },
|
||||
|
||||
//{ "R", L("Auto orientates selected objects or all objects.If there are selected objects, it just orientates the selected ones.Otherwise, it will orientates all objects in the project.") },
|
||||
{"Shift+R", L("Auto orientates selected objects or all objects.If there are selected objects, it just orientates the selected ones.Otherwise, it will orientates all objects in the current disk.")},
|
||||
{L("Shift+R"), L("Auto orientates selected objects or all objects.If there are selected objects, it just orientates the selected ones.Otherwise, it will orientates all objects in the current disk.")},
|
||||
|
||||
{"Shift+Tab", L("Collapse/Expand the sidebar")},
|
||||
{L("Shift+Tab"), L("Collapse/Expand the sidebar")},
|
||||
#ifdef __APPLE__
|
||||
{L("⌘+Any arrow"), L("Movement in camera space")},
|
||||
{L("⌥+Left mouse button"), L("Select a part")},
|
||||
|
|
@ -230,7 +235,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
{L("Arrow Left"), L("Move selection 10 mm in negative X direction")},
|
||||
{L("Arrow Right"), L("Move selection 10 mm in positive X direction")},
|
||||
{L("Shift+Any arrow"), L("Movement step set to 1 mm")},
|
||||
{"Esc", L("Deselect all")},
|
||||
{L("Esc"), L("Deselect all")},
|
||||
{"1-9", L("keyboard 1-9: set filament for object/part")},
|
||||
{ctrl + "0", L("Camera view - Default")},
|
||||
{ctrl + "1", L("Camera view - Top")},
|
||||
|
|
@ -257,8 +262,8 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
m_full_shortcuts.push_back({ { _L("Plater"), "" }, plater_shortcuts });
|
||||
|
||||
Shortcuts gizmos_shortcuts = {
|
||||
{"Esc", L("Deselect all")},
|
||||
{"Shift+", L("Move: press to snap by 1mm") },
|
||||
{L("Esc"), L("Deselect all")},
|
||||
{L("Shift+"), L("Move: press to snap by 1mm")},
|
||||
#ifdef __APPLE__
|
||||
{L("⌘+Mouse wheel"), L("Support/Color Painting: adjust pen radius")},
|
||||
{L("⌥+Mouse wheel"), L("Support/Color Painting: adjust section position")},
|
||||
|
|
@ -271,8 +276,8 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
|
||||
Shortcuts object_list_shortcuts = {
|
||||
{"1-9", L("Set extruder number for the objects and parts") },
|
||||
{"Del", L("Delete objects, parts, modifiers ")},
|
||||
{"Esc", L("Deselect all")},
|
||||
{L("Del"), L("Delete objects, parts, modifiers ")},
|
||||
{L("Esc"), L("Deselect all")},
|
||||
{ctrl + "C", L("Copy to clipboard")},
|
||||
{ctrl + "V", L("Paste from clipboard")},
|
||||
{ctrl + "X", L("Cut")},
|
||||
|
|
|
|||
|
|
@ -180,6 +180,10 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
|||
|
||||
wxGetApp().app_config->set_bool("dump_video", false);
|
||||
|
||||
wxString max_recent_count_str = wxGetApp().app_config->get("max_recent_count");
|
||||
long max_recent_count = 18;
|
||||
if (max_recent_count_str.ToLong(&max_recent_count))
|
||||
set_max_recent_count((int)max_recent_count);
|
||||
|
||||
//reset log level
|
||||
auto loglevel = wxGetApp().app_config->get("severity_level");
|
||||
|
|
@ -490,10 +494,14 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
|||
update_slice_print_status(eEventSliceUpdate, true, true);
|
||||
|
||||
// BBS: backup project
|
||||
std::string backup_interval;
|
||||
if (!wxGetApp().app_config->get("", "backup_interval", backup_interval))
|
||||
backup_interval = "10";
|
||||
Slic3r::set_backup_interval(boost::lexical_cast<long>(backup_interval));
|
||||
if (wxGetApp().app_config->get("backup_switch") == "true") {
|
||||
std::string backup_interval;
|
||||
if (!wxGetApp().app_config->get("", "backup_interval", backup_interval))
|
||||
backup_interval = "10";
|
||||
Slic3r::set_backup_interval(boost::lexical_cast<long>(backup_interval));
|
||||
} else {
|
||||
Slic3r::set_backup_interval(0);
|
||||
}
|
||||
Slic3r::set_backup_callback([this](int action) {
|
||||
if (action == 0) {
|
||||
wxPostEvent(this, wxCommandEvent(EVT_BACKUP_POST));
|
||||
|
|
@ -808,6 +816,11 @@ void MainFrame::shutdown()
|
|||
m_plater->get_mouse3d_controller().save_config(*wxGetApp().app_config);
|
||||
}
|
||||
|
||||
// stop agent
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (agent)
|
||||
agent->track_enable(false);
|
||||
|
||||
// Stop the background thread of the removable drive manager, so that no new updates will be sent to the Plater.
|
||||
//wxGetApp().removable_drive_manager()->shutdown();
|
||||
//stop listening for messages from other instances
|
||||
|
|
@ -993,10 +1006,9 @@ void MainFrame::init_tabpanel() {
|
|||
});
|
||||
m_printer_view->Hide();
|
||||
|
||||
m_auxiliary = new AuxiliaryPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_auxiliary->SetBackgroundColour(*wxWHITE);
|
||||
m_tabpanel->AddPage(m_auxiliary, _L("Project"), std::string("tab_auxiliary_avtice"), std::string("tab_auxiliary_avtice"));
|
||||
|
||||
m_project = new ProjectPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_project->SetBackgroundColour(*wxWHITE);
|
||||
m_tabpanel->AddPage(m_project, _L("Project"), std::string("tab_auxiliary_avtice"), std::string("tab_auxiliary_avtice"));
|
||||
if (m_plater) {
|
||||
// load initial config
|
||||
auto full_config = wxGetApp().preset_bundle->full_config();
|
||||
|
|
@ -1131,6 +1143,7 @@ void MainFrame::create_preset_tabs()
|
|||
add_created_tab(new TabPrint(m_param_panel), "cog");
|
||||
add_created_tab(new TabPrintObject(m_param_panel), "cog");
|
||||
add_created_tab(new TabPrintPart(m_param_panel), "cog");
|
||||
add_created_tab(new TabPrintLayer(m_param_panel), "cog");
|
||||
add_created_tab(new TabFilament(m_param_dialog->panel()), "spool");
|
||||
/* BBS work around to avoid appearance bug */
|
||||
//add_created_tab(new TabSLAPrint(m_param_panel));
|
||||
|
|
@ -1839,7 +1852,7 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect)
|
|||
//BBS GUI refactor: remove unused layout new/dlg
|
||||
//if (m_layout != ESettingsLayout::Dlg) // Do not update tabs if the Settings are in the separated dialog
|
||||
m_param_panel->msw_rescale();
|
||||
m_auxiliary->msw_rescale();
|
||||
m_project->msw_rescale();
|
||||
m_monitor->msw_rescale();
|
||||
|
||||
// BBS
|
||||
|
|
@ -2009,26 +2022,27 @@ static void add_common_publish_menu_items(wxMenu* publish_menu, MainFrame* mainF
|
|||
|
||||
static void add_common_view_menu_items(wxMenu* view_menu, MainFrame* mainFrame, std::function<bool(void)> can_change_view)
|
||||
{
|
||||
const wxString ctrl = _L("Ctrl+");
|
||||
// The camera control accelerators are captured by GLCanvas3D::on_char().
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Default View") + "\tCtrl+0", _L("Default View"), [mainFrame](wxCommandEvent&) {
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Default View") + "\t" + ctrl + "0", _L("Default View"), [mainFrame](wxCommandEvent&) {
|
||||
mainFrame->select_view("plate");
|
||||
mainFrame->plater()->get_current_canvas3D()->zoom_to_bed();
|
||||
},
|
||||
"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
|
||||
//view_menu->AppendSeparator();
|
||||
//TRN To be shown in the main menu View->Top
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Top") + "\tCtrl+1", _L("Top View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("top"); },
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Top") + "\t" + ctrl + "1", _L("Top View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("top"); },
|
||||
"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
|
||||
//TRN To be shown in the main menu View->Bottom
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Bottom") + "\tCtrl+2", _L("Bottom View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("bottom"); },
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Bottom") + "\t" + ctrl + "2", _L("Bottom View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("bottom"); },
|
||||
"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Front") + "\tCtrl+3", _L("Front View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("front"); },
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Front") + "\t" + ctrl + "3", _L("Front View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("front"); },
|
||||
"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Rear") + "\tCtrl+4", _L("Rear View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("rear"); },
|
||||
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, _L("Left") + "\tCtrl+5", _L("Left View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("left"); },
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Left") + "\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, _L("Right") + "\tCtrl+6", _L("Right View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("right"); },
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Right") + "\t" + ctrl + "6", _L("Right View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("right"); },
|
||||
"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
|
||||
}
|
||||
|
||||
|
|
@ -2038,6 +2052,8 @@ void MainFrame::init_menubar_as_editor()
|
|||
wxMenuBar::SetAutoWindowMenu(false);
|
||||
m_menubar = new wxMenuBar();
|
||||
#endif
|
||||
|
||||
const wxString ctrl = _L("Ctrl+");
|
||||
|
||||
// File menu
|
||||
wxMenu* fileMenu = new wxMenu;
|
||||
|
|
@ -2049,17 +2065,17 @@ void MainFrame::init_menubar_as_editor()
|
|||
[]{ return true; }, this);
|
||||
#endif
|
||||
// New Project
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("New Project") + "\tCtrl+N", _L("Start a new project"),
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("New Project") + "\t" + ctrl + "N", _L("Start a new project"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->new_project(); }, "", nullptr,
|
||||
[this](){return can_start_new_project(); }, this);
|
||||
// Open Project
|
||||
|
||||
#ifndef __APPLE__
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Open Project") + dots + "\tCtrl+O", _L("Open a project file"),
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Open Project") + dots + "\t" + ctrl + "O", _L("Open a project file"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "menu_open", nullptr,
|
||||
[this](){return can_open_project(); }, this);
|
||||
#else
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Open Project") + dots + "\tCtrl+O", _L("Open a project file"),
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Open Project") + dots + "\t" + ctrl + "O", _L("Open a project file"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "", nullptr,
|
||||
[this](){return can_open_project(); }, this);
|
||||
#endif
|
||||
|
|
@ -2086,22 +2102,22 @@ void MainFrame::init_menubar_as_editor()
|
|||
|
||||
// BBS: close save project
|
||||
#ifndef __APPLE__
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project") + "\tCtrl+S", _L("Save current project to file"),
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project") + "\t" + ctrl + "S", _L("Save current project to file"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->save_project(); }, "menu_save", nullptr,
|
||||
[this](){return m_plater != nullptr && can_save(); }, this);
|
||||
#else
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project") + "\tCtrl+S", _L("Save current project to file"),
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project") + "\t" + ctrl + "S", _L("Save current project to file"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->save_project(); }, "", nullptr,
|
||||
[this](){return m_plater != nullptr && can_save(); }, this);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __APPLE__
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project as") + dots + "\tCtrl+Shift+S", _L("Save current project as"),
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project as") + dots + "\t" + ctrl + _L("Shift+") + "S", _L("Save current project as"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->save_project(true); }, "menu_save", nullptr,
|
||||
[this](){return m_plater != nullptr && can_save_as(); }, this);
|
||||
#else
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project as") + dots + "\tCtrl+Shift+S", _L("Save current project as"),
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project as") + dots + "\t" + ctrl + _L("Shift+") + "S", _L("Save current project as"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->save_project(true); }, "", nullptr,
|
||||
[this](){return m_plater != nullptr && can_save_as(); }, this);
|
||||
#endif
|
||||
|
|
@ -2112,13 +2128,13 @@ void MainFrame::init_menubar_as_editor()
|
|||
// BBS
|
||||
wxMenu *import_menu = new wxMenu();
|
||||
#ifndef __APPLE__
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import 3MF/STL/STEP/SVG/OBJ/AMF") + dots + "\tCtrl+I", _L("Load a model"),
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import 3MF/STL/STEP/SVG/OBJ/AMF") + dots + "\t" + ctrl + "I", _L("Load a model"),
|
||||
[this](wxCommandEvent&) { if (m_plater) {
|
||||
m_plater->add_file();
|
||||
} }, "menu_import", nullptr,
|
||||
[this](){return can_add_models(); }, this);
|
||||
#else
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import 3MF/STL/STEP/SVG/OBJ/AMF") + dots + "\tCtrl+I", _L("Load a model"),
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import 3MF/STL/STEP/SVG/OBJ/AMF") + dots + "\t" + ctrl + "I", _L("Load a model"),
|
||||
[this](wxCommandEvent&) { if (m_plater) { m_plater->add_model(); } }, "", nullptr,
|
||||
[this](){return can_add_models(); }, this);
|
||||
#endif
|
||||
|
|
@ -2138,7 +2154,7 @@ void MainFrame::init_menubar_as_editor()
|
|||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_core_3mf(); }, "menu_export_sliced_file", nullptr,
|
||||
[this](){return can_export_model(); }, this);
|
||||
// BBS export .gcode.3mf
|
||||
append_menu_item(export_menu, wxID_ANY, _L("Export plate sliced file") + dots + "\tCtrl+G", _L("Export current sliced file"),
|
||||
append_menu_item(export_menu, wxID_ANY, _L("Export plate sliced file") + dots + "\t" + ctrl + "G", _L("Export current sliced file"),
|
||||
[this](wxCommandEvent&) { if (m_plater) wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_SLICED_FILE)); }, "menu_export_sliced_file", nullptr,
|
||||
[this](){return can_export_gcode(); }, this);
|
||||
|
||||
|
|
@ -2180,34 +2196,41 @@ void MainFrame::init_menubar_as_editor()
|
|||
wxString hotkey_delete = "Del";
|
||||
#endif
|
||||
|
||||
auto handle_key_event = [](wxKeyEvent& evt) {
|
||||
if (wxGetApp().imgui()->update_key_data(evt)) {
|
||||
wxGetApp().plater()->get_current_canvas3D()->render();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
#ifndef __APPLE__
|
||||
// BBS undo
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Undo") + "\tCtrl+Z",
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Undo") + "\t" + ctrl + "Z",
|
||||
_L("Undo"), [this](wxCommandEvent&) { m_plater->undo(); },
|
||||
"menu_undo", nullptr, [this](){return m_plater->can_undo(); }, this);
|
||||
// BBS redo
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Redo") + "\tCtrl+Y",
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Redo") + "\t" + ctrl + "Y",
|
||||
_L("Redo"), [this](wxCommandEvent&) { m_plater->redo(); },
|
||||
"menu_redo", nullptr, [this](){return m_plater->can_redo(); }, this);
|
||||
editMenu->AppendSeparator();
|
||||
// BBS Cut TODO
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Cut") + "\tCtrl+X",
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Cut") + "\t" + ctrl + "X",
|
||||
_L("Cut selection to clipboard"), [this](wxCommandEvent&) {m_plater->cut_selection_to_clipboard(); },
|
||||
"menu_cut", nullptr, [this]() {return m_plater->can_copy_to_clipboard(); }, this);
|
||||
// BBS Copy
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Copy") + "\tCtrl+C",
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Copy") + "\t" + ctrl + "C",
|
||||
_L("Copy selection to clipboard"), [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); },
|
||||
"menu_copy", nullptr, [this](){return m_plater->can_copy_to_clipboard(); }, this);
|
||||
// BBS Paste
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Paste") + "\tCtrl+V",
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Paste") + "\t" + ctrl + "V",
|
||||
_L("Paste clipboard"), [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); },
|
||||
"menu_paste", nullptr, [this](){return m_plater->can_paste_from_clipboard(); }, this);
|
||||
// BBS Delete selected
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Delete selected") + "\tDel",
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Delete selected") + "\t" + _L("Del"),
|
||||
_L("Deletes the current selection"),[this](wxCommandEvent&) { m_plater->remove_selected(); },
|
||||
"menu_remove", nullptr, [this](){return can_delete(); }, this);
|
||||
//BBS: delete all
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Delete all") + "\tCtrl+D",
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Delete all") + "\t" + ctrl + "D",
|
||||
_L("Deletes all objects"),[this](wxCommandEvent&) { m_plater->delete_all_objects_from_model(); },
|
||||
"menu_remove", nullptr, [this](){return can_delete_all(); }, this);
|
||||
editMenu->AppendSeparator();
|
||||
|
|
@ -2220,40 +2243,97 @@ void MainFrame::init_menubar_as_editor()
|
|||
editMenu->AppendSeparator();
|
||||
#else
|
||||
// BBS undo
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Undo") + "\tCtrl+Z",
|
||||
_L("Undo"), [this](wxCommandEvent&) { m_plater->undo(); },
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Undo") + "\t" + ctrl + "Z",
|
||||
_L("Undo"), [this, handle_key_event](wxCommandEvent&) {
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.SetControlDown(true);
|
||||
e.m_keyCode = 'Z';
|
||||
if (handle_key_event(e)) {
|
||||
return;
|
||||
}
|
||||
m_plater->undo(); },
|
||||
"", nullptr, [this](){return m_plater->can_undo(); }, this);
|
||||
// BBS redo
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Redo") + "\tCtrl+Y",
|
||||
_L("Redo"), [this](wxCommandEvent&) { m_plater->redo(); },
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Redo") + "\t" + ctrl + "Y",
|
||||
_L("Redo"), [this, handle_key_event](wxCommandEvent&) {
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.SetControlDown(true);
|
||||
e.m_keyCode = 'Y';
|
||||
if (handle_key_event(e)) {
|
||||
return;
|
||||
}
|
||||
m_plater->redo(); },
|
||||
"", nullptr, [this](){return m_plater->can_redo(); }, this);
|
||||
editMenu->AppendSeparator();
|
||||
// BBS Cut TODO
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Cut") + "\tCtrl+X",
|
||||
_L("Cut selection to clipboard"), [this](wxCommandEvent&) {m_plater->cut_selection_to_clipboard(); },
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Cut") + "\t" + ctrl + "X",
|
||||
_L("Cut selection to clipboard"), [this, handle_key_event](wxCommandEvent&) {
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.SetControlDown(true);
|
||||
e.m_keyCode = 'X';
|
||||
if (handle_key_event(e)) {
|
||||
return;
|
||||
}
|
||||
m_plater->cut_selection_to_clipboard(); },
|
||||
"", nullptr, [this]() {return m_plater->can_copy_to_clipboard(); }, this);
|
||||
// BBS Copy
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Copy") + "\tCtrl+C",
|
||||
_L("Copy selection to clipboard"), [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); },
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Copy") + "\t" + ctrl + "C",
|
||||
_L("Copy selection to clipboard"), [this, handle_key_event](wxCommandEvent&) {
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.SetControlDown(true);
|
||||
e.m_keyCode = 'C';
|
||||
if (handle_key_event(e)) {
|
||||
return;
|
||||
}
|
||||
m_plater->copy_selection_to_clipboard(); },
|
||||
"", nullptr, [this](){return m_plater->can_copy_to_clipboard(); }, this);
|
||||
// BBS Paste
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Paste") + "\tCtrl+V",
|
||||
_L("Paste clipboard"), [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); },
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Paste") + "\t" + ctrl + "V",
|
||||
_L("Paste clipboard"), [this, handle_key_event](wxCommandEvent&) {
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.SetControlDown(true);
|
||||
e.m_keyCode = 'V';
|
||||
if (handle_key_event(e)) {
|
||||
return;
|
||||
}
|
||||
m_plater->paste_from_clipboard(); },
|
||||
"", nullptr, [this](){return m_plater->can_paste_from_clipboard(); }, this);
|
||||
#if 0
|
||||
// BBS Delete selected
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Delete selected") + "\tBackSpace",
|
||||
_L("Deletes the current selection"),[this](wxCommandEvent&) { m_plater->remove_selected(); },
|
||||
_L("Deletes the current selection"),[this](wxCommandEvent&) {
|
||||
m_plater->remove_selected();
|
||||
},
|
||||
"", nullptr, [this](){return can_delete(); }, this);
|
||||
#endif
|
||||
//BBS: delete all
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Delete all") + "\tCtrl+D",
|
||||
_L("Deletes all objects"),[this](wxCommandEvent&) { m_plater->delete_all_objects_from_model(); },
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Delete all") + "\t" + ctrl + "D",
|
||||
_L("Deletes all objects"),[this, handle_key_event](wxCommandEvent&) {
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.SetControlDown(true);
|
||||
e.m_keyCode = 'D';
|
||||
if (handle_key_event(e)) {
|
||||
return;
|
||||
}
|
||||
m_plater->delete_all_objects_from_model(); },
|
||||
"", nullptr, [this](){return can_delete_all(); }, this);
|
||||
editMenu->AppendSeparator();
|
||||
// BBS Clone Selected
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Clone selected") + "\tCtrl+M",
|
||||
_L("Clone copies of selections"),[this](wxCommandEvent&) {
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Clone selected") + "\t" + ctrl + "M",
|
||||
_L("Clone copies of selections"),[this, handle_key_event](wxCommandEvent&) {
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.SetControlDown(true);
|
||||
e.m_keyCode = 'M';
|
||||
if (handle_key_event(e)) {
|
||||
return;
|
||||
}
|
||||
m_plater->clone_selection();
|
||||
},
|
||||
"", nullptr, [this](){return can_clone(); }, this);
|
||||
|
|
@ -2261,12 +2341,27 @@ void MainFrame::init_menubar_as_editor()
|
|||
#endif
|
||||
|
||||
// BBS Select All
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Select all") + "\tCtrl+A",
|
||||
_L("Selects all objects"), [this](wxCommandEvent&) { m_plater->select_all(); },
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Select all") + "\t" + ctrl + "A",
|
||||
_L("Selects all objects"), [this, handle_key_event](wxCommandEvent&) {
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.SetControlDown(true);
|
||||
e.m_keyCode = 'A';
|
||||
if (handle_key_event(e)) {
|
||||
return;
|
||||
}
|
||||
m_plater->select_all(); },
|
||||
"", nullptr, [this](){return can_select(); }, this);
|
||||
// BBS Deslect All
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Deselect all") + "\tEsc",
|
||||
_L("Deselects all objects"), [this](wxCommandEvent&) { m_plater->deselect_all(); },
|
||||
_L("Deselects all objects"), [this, handle_key_event](wxCommandEvent&) {
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.m_keyCode = WXK_ESCAPE;
|
||||
if (handle_key_event(e)) {
|
||||
return;
|
||||
}
|
||||
m_plater->deselect_all(); },
|
||||
"", nullptr, [this](){return can_deselect(); }, this);
|
||||
//editMenu->AppendSeparator();
|
||||
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Mesh(TODO)"),
|
||||
|
|
@ -2320,7 +2415,7 @@ void MainFrame::init_menubar_as_editor()
|
|||
viewMenu->Check(wxID_CAMERA_ORTHOGONAL + camera_id_base, true);
|
||||
|
||||
viewMenu->AppendSeparator();
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels") + "\tCtrl+E", _L("Show object labels in 3D scene"),
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels") + "\t" + ctrl + "E", _L("Show object labels in 3D scene"),
|
||||
[this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this,
|
||||
[this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this);
|
||||
|
||||
|
|
@ -2351,7 +2446,7 @@ void MainFrame::init_menubar_as_editor()
|
|||
//auto preference_item = new wxMenuItem(parent_menu, BambuStudioMenuPreferences + bambu_studio_id_base, _L("Preferences") + "\tCtrl+,", "");
|
||||
#else
|
||||
wxMenu* parent_menu = m_topbar->GetTopMenu();
|
||||
auto preference_item = new wxMenuItem(parent_menu, ConfigMenuPreferences + config_id_base, _L("Preferences") + "\tCtrl+P", "");
|
||||
auto preference_item = new wxMenuItem(parent_menu, ConfigMenuPreferences + config_id_base, _L("Preferences") + "\t" + ctrl + "P", "");
|
||||
|
||||
#endif
|
||||
//auto printer_item = new wxMenuItem(parent_menu, ConfigMenuPrinter + config_id_base, _L("Printer"), "");
|
||||
|
|
@ -2393,7 +2488,7 @@ void MainFrame::init_menubar_as_editor()
|
|||
// }
|
||||
// case ConfigMenuPreferences:
|
||||
// {
|
||||
// wxGetApp().CallAfter([this] {
|
||||
// CallAfter([this] {
|
||||
// PreferencesDialog dlg(this);
|
||||
// dlg.ShowModal();
|
||||
//#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
|
@ -2430,7 +2525,7 @@ void MainFrame::init_menubar_as_editor()
|
|||
// Slic3r::GUI::about();
|
||||
// break;
|
||||
// case BambuStudioMenuPreferences:
|
||||
// wxGetApp().CallAfter([this] {
|
||||
// CallAfter([this] {
|
||||
// PreferencesDialog dlg(this);
|
||||
// dlg.ShowModal();
|
||||
//#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
|
@ -2451,7 +2546,7 @@ void MainFrame::init_menubar_as_editor()
|
|||
[this](wxCommandEvent &) { Slic3r::GUI::about();},
|
||||
"", nullptr, []() { return true; }, this, 0);
|
||||
append_menu_item(
|
||||
parent_menu, wxID_ANY, _L("Preferences") + "\tCtrl+,", "",
|
||||
parent_menu, wxID_ANY, _L("Preferences") + "\t" + ctrl + ",", "",
|
||||
[this](wxCommandEvent &) {
|
||||
PreferencesDialog dlg(this);
|
||||
dlg.ShowModal();
|
||||
|
|
@ -2478,7 +2573,7 @@ void MainFrame::init_menubar_as_editor()
|
|||
//BBS add Preference
|
||||
|
||||
append_menu_item(
|
||||
m_topbar->GetTopMenu(), wxID_ANY, _L("Preferences") + "\tCtrl+P", "",
|
||||
m_topbar->GetTopMenu(), wxID_ANY, _L("Preferences") + "\t" + ctrl + "P", "",
|
||||
[this](wxCommandEvent &) {
|
||||
PreferencesDialog dlg(this);
|
||||
dlg.ShowModal();
|
||||
|
|
@ -2654,6 +2749,23 @@ void MainFrame::show_publish_button(bool show)
|
|||
}
|
||||
}
|
||||
|
||||
void MainFrame::set_max_recent_count(int max)
|
||||
{
|
||||
max = max < 0 ? 0 : max > 10000 ? 10000 : max;
|
||||
size_t count = m_recent_projects.GetCount();
|
||||
m_recent_projects.SetMaxFiles(max);
|
||||
if (count != m_recent_projects.GetCount()) {
|
||||
count = m_recent_projects.GetCount();
|
||||
std::vector<std::string> recent_projects;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
recent_projects.push_back(into_u8(m_recent_projects.GetHistoryFile(i)));
|
||||
}
|
||||
wxGetApp().app_config->set_recent_projects(recent_projects);
|
||||
wxGetApp().app_config->save();
|
||||
m_webview->SendRecentList("");
|
||||
}
|
||||
}
|
||||
|
||||
void MainFrame::open_menubar_item(const wxString& menu_name,const wxString& item_name)
|
||||
{
|
||||
if (m_menubar == nullptr)
|
||||
|
|
@ -3163,6 +3275,14 @@ void MainFrame::FileHistory::LoadThumbnails()
|
|||
m_load_called = true;
|
||||
}
|
||||
|
||||
inline void MainFrame::FileHistory::SetMaxFiles(int max)
|
||||
{
|
||||
m_fileMaxFiles = max;
|
||||
size_t numFiles = m_fileHistory.size();
|
||||
while (numFiles > m_fileMaxFiles)
|
||||
RemoveFileFromHistory(--numFiles);
|
||||
}
|
||||
|
||||
void MainFrame::get_recent_projects(boost::property_tree::wptree &tree)
|
||||
{
|
||||
for (size_t i = 0; i < m_recent_projects.GetCount(); ++i) {
|
||||
|
|
@ -3190,7 +3310,7 @@ void MainFrame::open_recent_project(size_t file_id, wxString const & filename)
|
|||
file_id = m_recent_projects.FindFileInHistory(filename);
|
||||
}
|
||||
if (wxFileExists(filename)) {
|
||||
wxGetApp().CallAfter([this, filename] {
|
||||
CallAfter([this, filename] {
|
||||
if (wxGetApp().can_load_project())
|
||||
m_plater->load_project(filename);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "ParamsPanel.hpp"
|
||||
#include "Monitor.hpp"
|
||||
#include "Auxiliary.hpp"
|
||||
#include "Project.hpp"
|
||||
#include "UnsavedChangesDialog.hpp"
|
||||
#include "Widgets/SideButton.hpp"
|
||||
#include "Widgets/SideMenuPopup.hpp"
|
||||
|
|
@ -156,6 +157,8 @@ class MainFrame : public DPIFrame
|
|||
size_t FindFileInHistory(const wxString &file);
|
||||
|
||||
void LoadThumbnails();
|
||||
|
||||
void SetMaxFiles(int max);
|
||||
private:
|
||||
std::deque<std::string> m_thumbnails;
|
||||
bool m_load_called = false;
|
||||
|
|
@ -245,6 +248,7 @@ public:
|
|||
|
||||
void update_title();
|
||||
void show_publish_button(bool show);
|
||||
void set_max_recent_count(int max);
|
||||
|
||||
void update_title_colour_after_set_title();
|
||||
void show_option(bool show);
|
||||
|
|
@ -344,7 +348,10 @@ public:
|
|||
Plater* m_plater { nullptr };
|
||||
//BBS: GUI refactor
|
||||
MonitorPanel* m_monitor{ nullptr };
|
||||
AuxiliaryPanel* m_auxiliary{ nullptr };
|
||||
|
||||
//AuxiliaryPanel* m_auxiliary{ nullptr };
|
||||
ProjectPanel* m_project{ nullptr };
|
||||
|
||||
WebViewPanel* m_webview { nullptr };
|
||||
PrinterWebView* m_printer_view{nullptr};
|
||||
wxLogWindow* m_log_window { nullptr };
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
|
|||
m_button_year = new ::Button(m_time_panel, _L("Year"), "", wxBORDER_NONE);
|
||||
m_button_month = new ::Button(m_time_panel, _L("Month"), "", wxBORDER_NONE);
|
||||
m_button_all = new ::Button(m_time_panel, _L("All Files"), "", wxBORDER_NONE);
|
||||
m_button_year->SetToolTip(L("Group files by year, recent first."));
|
||||
m_button_month->SetToolTip(L("Group files by month, recent first."));
|
||||
m_button_all->SetToolTip(L("Show all files, recent first."));
|
||||
m_button_year->SetToolTip(_L("Group files by year, recent first."));
|
||||
m_button_month->SetToolTip(_L("Group files by month, recent first."));
|
||||
m_button_all->SetToolTip(_L("Show all files, recent first."));
|
||||
m_button_all->SetFont(Label::Head_14); // sync with m_last_mode
|
||||
for (auto b : {m_button_year, m_button_month, m_button_all}) {
|
||||
b->SetBackgroundColor(StateColor());
|
||||
|
|
@ -228,14 +228,15 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
|
|||
m_button_download->Enable(e.GetInt() > 0);
|
||||
});
|
||||
fs->Bind(EVT_MODE_CHANGED, &MediaFilePanel::modeChanged, this);
|
||||
fs->Bind(EVT_STATUS_CHANGED, [this, wfs = boost::weak_ptr(fs)](auto &e) {
|
||||
fs->Bind(EVT_STATUS_CHANGED, [this, wfs = boost::weak_ptr(fs)](auto& e) {
|
||||
e.Skip();
|
||||
boost::shared_ptr fs(wfs.lock());
|
||||
if (m_image_grid->GetFileSystem() != fs) // canceled
|
||||
return;
|
||||
ScalableBitmap icon;
|
||||
wxString msg;
|
||||
switch (e.GetInt()) {
|
||||
int status = e.GetInt();
|
||||
switch (status) {
|
||||
case PrinterFileSystem::Initializing: icon = m_bmp_loading; msg = _L("Initializing..."); break;
|
||||
case PrinterFileSystem::Connecting: icon = m_bmp_loading; msg = _L("Connecting..."); break;
|
||||
case PrinterFileSystem::Failed: icon = m_bmp_failed; msg = _L("Connect failed [%d]!"); break;
|
||||
|
|
@ -246,6 +247,53 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
|
|||
m_image_grid->SetStatus(icon, msg);
|
||||
if (e.GetInt() == PrinterFileSystem::Initializing)
|
||||
fetchUrl(boost::weak_ptr(fs));
|
||||
|
||||
if (status == PrinterFileSystem::Failed
|
||||
|| status == PrinterFileSystem::ListReady) {
|
||||
json j;
|
||||
j["code"] = fs->GetLastError();
|
||||
j["dev_id"] = m_machine;
|
||||
j["dev_ip"] = m_lan_ip;
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (status == PrinterFileSystem::Failed) {
|
||||
j["result"] = "failed";
|
||||
if (agent)
|
||||
agent->track_event("download_video_conn", j.dump());
|
||||
} else if (status == PrinterFileSystem::ListReady) {
|
||||
j["result"] = "success";
|
||||
if (agent)
|
||||
agent->track_event("download_video_conn", j.dump());
|
||||
}
|
||||
}
|
||||
});
|
||||
fs->Bind(EVT_DOWNLOAD, [this, wfs = boost::weak_ptr(fs)](auto& e) {
|
||||
e.Skip();
|
||||
boost::shared_ptr fs(wfs.lock());
|
||||
if (m_image_grid->GetFileSystem() != fs) // canceled
|
||||
return;
|
||||
|
||||
int result = e.GetExtraLong();
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (result > 1 || result == 0) {
|
||||
json j;
|
||||
j["code"] = result;
|
||||
j["dev_id"] = m_machine;
|
||||
j["dev_ip"] = m_lan_ip;
|
||||
if (result > 1) {
|
||||
// download failed
|
||||
j["result"] = "failed";
|
||||
if (agent) {
|
||||
agent->track_event("download_video", j.dump());
|
||||
}
|
||||
} else if (result == 0) {
|
||||
// download success
|
||||
j["result"] = "success";
|
||||
if (agent) {
|
||||
agent->track_event("download_video", j.dump());
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
});
|
||||
if (IsShown()) fs->Start();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,6 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const w
|
|||
{
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
m_media_ctrl->Bind(wxEVT_MEDIA_STATECHANGED, &MediaPlayCtrl::onStateChanged, this);
|
||||
#if wxUSE_GSTREAMER_PLAYER
|
||||
m_media_ctrl->Bind(wxEVT_MEDIA_LOADED, &MediaPlayCtrl::onStateChanged, this);
|
||||
#endif
|
||||
|
||||
m_button_play = new Button(this, "", "media_play", wxBORDER_NONE);
|
||||
m_button_play->SetCanFocus(false);
|
||||
|
|
@ -195,8 +192,8 @@ void MediaPlayCtrl::Play()
|
|||
m_url = url;
|
||||
if (m_last_state == MEDIASTATE_INITIALIZING) {
|
||||
if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
Stop();
|
||||
SetStatus(wxString::Format(_L("Initialize failed (%s)!"), url.empty() ? _L("Network unreachable") : from_u8(url)));
|
||||
m_failed_code = 3;
|
||||
Stop(wxString::Format(_L("Initialize failed (%s)!"), url.empty() ? _L("Network unreachable") : from_u8(url)));
|
||||
} else {
|
||||
m_last_state = MEDIASTATE_LOADING;
|
||||
SetStatus(_L("Loading..."));
|
||||
|
|
@ -218,6 +215,8 @@ void MediaPlayCtrl::Play()
|
|||
|
||||
void MediaPlayCtrl::Stop(wxString const &msg)
|
||||
{
|
||||
bool init_failed = m_last_state != wxMEDIASTATE_PLAYING;
|
||||
|
||||
if (m_last_state != MEDIASTATE_IDLE) {
|
||||
m_media_ctrl->InvalidateBestSize();
|
||||
m_button_play->SetIcon("media_play");
|
||||
|
|
@ -235,13 +234,31 @@ void MediaPlayCtrl::Stop(wxString const &msg)
|
|||
m_next_retry = wxDateTime();
|
||||
} else if (!msg.IsEmpty()) {
|
||||
SetStatus(msg, false);
|
||||
} else {
|
||||
m_failed_code = 0;
|
||||
}
|
||||
|
||||
if (init_failed && m_failed_code != 0 && m_last_failed_code != m_failed_code) {
|
||||
json j;
|
||||
j["stage"] = std::to_string(m_last_state);
|
||||
j["dev_id"] = m_machine;
|
||||
j["dev_ip"] = m_lan_ip;
|
||||
j["result"] = "failed";
|
||||
j["code"] = m_failed_code;
|
||||
j["msg"] = into_u8(msg);
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
if (agent)
|
||||
agent->track_event("start_liveview", j.dump());
|
||||
}
|
||||
m_last_failed_code = m_failed_code;
|
||||
|
||||
++m_failed_retry;
|
||||
if (m_failed_code != 0 && !m_tutk_support && (m_failed_retry > 1 || m_user_triggered)) {
|
||||
m_next_retry = wxDateTime(); // stop retry
|
||||
if (wxGetApp().show_modal_ip_address_enter_dialog(_L("LAN Connection Failed (Failed to start liveview)"))) {
|
||||
m_failed_retry = 0;
|
||||
m_user_triggered = true;
|
||||
m_last_failed_code = 0;
|
||||
m_next_retry = wxDateTime::Now();
|
||||
return;
|
||||
}
|
||||
|
|
@ -259,6 +276,7 @@ void MediaPlayCtrl::TogglePlay()
|
|||
} else {
|
||||
m_failed_retry = 0;
|
||||
m_user_triggered = true;
|
||||
m_last_failed_code = 0;
|
||||
m_next_retry = wxDateTime::Now();
|
||||
Play();
|
||||
}
|
||||
|
|
@ -301,7 +319,7 @@ void MediaPlayCtrl::ToggleStream()
|
|||
{ return std::make_shared<UpgradeNetworkJob2>(pri); }
|
||||
void on_finish() override
|
||||
{
|
||||
wxGetApp().CallAfter([ctrl = this->ctrl] { ctrl->ToggleStream(); });
|
||||
ctrl->CallAfter([ctrl = this->ctrl] { ctrl->ToggleStream(); });
|
||||
EndModal(wxID_CLOSE);
|
||||
}
|
||||
};
|
||||
|
|
@ -365,23 +383,34 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
|||
Stop();
|
||||
return;
|
||||
}
|
||||
if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED || event.GetEventType() == wxEVT_MEDIA_LOADED)) {
|
||||
if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED)) {
|
||||
wxSize size = m_media_ctrl->GetVideoSize();
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
|
||||
m_failed_code = m_media_ctrl->GetLastError();
|
||||
if (size.GetWidth() > 1000 || (event.GetEventType() == wxEVT_MEDIA_LOADED)) {
|
||||
if (size.GetWidth() > 1000) {
|
||||
m_last_state = state;
|
||||
SetStatus(_L("Playing..."), false);
|
||||
|
||||
// track event
|
||||
json j;
|
||||
j["stage"] = std::to_string(m_last_state);
|
||||
j["dev_id"] = m_machine;
|
||||
j["dev_ip"] = m_lan_ip;
|
||||
j["result"] = "success";
|
||||
j["code"] = 0;
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (agent)
|
||||
agent->track_event("start_liveview", j.dump());
|
||||
|
||||
m_failed_retry = 0;
|
||||
m_failed_code = 0;
|
||||
boost::unique_lock lock(m_mutex);
|
||||
m_tasks.push_back("<play>");
|
||||
m_cond.notify_all();
|
||||
} else if (event.GetId()) {
|
||||
Stop();
|
||||
if (m_failed_code == 0)
|
||||
m_failed_code = 2;
|
||||
SetStatus(_L("Load failed [%d]!"));
|
||||
Stop(_L("Load failed [%d]!"));
|
||||
}
|
||||
} else {
|
||||
m_last_state = state;
|
||||
|
|
@ -563,7 +592,7 @@ void wxMediaCtrl2::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
|||
if (maxHeight != GetMaxHeight()) {
|
||||
// BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl2::DoSetSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight;
|
||||
SetMaxSize({-1, maxHeight});
|
||||
Slic3r::GUI::wxGetApp().CallAfter([this] {
|
||||
CallAfter([this] {
|
||||
if (auto p = GetParent()) {
|
||||
p->Layout();
|
||||
p->Refresh();
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ private:
|
|||
bool m_user_triggered = false;
|
||||
int m_failed_retry = 0;
|
||||
int m_failed_code = 0;
|
||||
int m_last_failed_code = 0;
|
||||
wxDateTime m_next_retry;
|
||||
|
||||
::Button *m_button_play;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <GL/glew.h>
|
||||
|
||||
#include <igl/unproject.h>
|
||||
#include "CameraUtils.hpp"
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
|
@ -75,7 +76,24 @@ void MeshClipper::render_cut()
|
|||
m_vertex_array.render();
|
||||
}
|
||||
|
||||
bool MeshClipper::is_projection_inside_cut(const Vec3d &point_in) const
|
||||
{
|
||||
if (!m_result || m_result->cut_islands.empty())
|
||||
return false;
|
||||
Vec3d point = m_result->trafo.inverse() * point_in;
|
||||
Point pt_2d = Point::new_scale(Vec2d(point.x(), point.y()));
|
||||
|
||||
for (const CutIsland &isl : m_result->cut_islands) {
|
||||
if (isl.expoly_bb.contains(pt_2d) && isl.expoly.contains(pt_2d))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MeshClipper::has_valid_contour() const
|
||||
{
|
||||
return m_result && std::any_of(m_result->cut_islands.begin(), m_result->cut_islands.end(), [](const CutIsland &isl) { return !isl.expoly.empty(); });
|
||||
}
|
||||
|
||||
void MeshClipper::recalculate_triangles()
|
||||
{
|
||||
|
|
@ -104,6 +122,9 @@ void MeshClipper::recalculate_triangles()
|
|||
tr.rotate(q);
|
||||
tr = m_trafo.get_matrix() * tr;
|
||||
|
||||
m_result = ClipResult();
|
||||
m_result->trafo = tr;
|
||||
|
||||
if (m_limiting_plane != ClippingPlane::ClipsNothing())
|
||||
{
|
||||
// Now remove whatever ended up below the limiting plane (e.g. sinking objects).
|
||||
|
|
@ -157,6 +178,13 @@ void MeshClipper::recalculate_triangles()
|
|||
}
|
||||
}
|
||||
|
||||
for (const ExPolygon &exp : expolys) {
|
||||
m_result->cut_islands.push_back(CutIsland());
|
||||
CutIsland &isl = m_result->cut_islands.back();
|
||||
isl.expoly = std::move(exp);
|
||||
isl.expoly_bb = get_extents(exp);
|
||||
}
|
||||
|
||||
m_triangles2d = triangulate_expolygons_2f(expolys, m_trafo.get_matrix().matrix().determinant() < 0.);
|
||||
|
||||
tr.pretranslate(0.001 * m_plane.get_normal().normalized()); // to avoid z-fighting
|
||||
|
|
@ -180,6 +208,14 @@ Vec3f MeshRaycaster::get_triangle_normal(size_t facet_idx) const
|
|||
return m_normals[facet_idx];
|
||||
}
|
||||
|
||||
void MeshRaycaster::line_from_mouse_pos_static(const Vec2d &mouse_pos, const Transform3d &trafo, const Camera &camera, Vec3d &point, Vec3d &direction)
|
||||
{
|
||||
CameraUtils::ray_from_screen_pos(camera, mouse_pos, point, direction);
|
||||
Transform3d inv = trafo.inverse();
|
||||
point = inv * point;
|
||||
direction = inv.linear() * direction;
|
||||
}
|
||||
|
||||
void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||
Vec3d& point, Vec3d& direction) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ public:
|
|||
// be set in world coords.
|
||||
void render_cut();
|
||||
|
||||
bool is_projection_inside_cut(const Vec3d &point) const;
|
||||
bool has_valid_contour() const;
|
||||
|
||||
private:
|
||||
void recalculate_triangles();
|
||||
|
||||
|
|
@ -105,6 +108,18 @@ private:
|
|||
std::vector<Vec2f> m_triangles2d;
|
||||
GLIndexedVertexArray m_vertex_array;
|
||||
bool m_triangles_valid = false;
|
||||
|
||||
struct CutIsland
|
||||
{
|
||||
ExPolygon expoly;
|
||||
BoundingBox expoly_bb;
|
||||
};
|
||||
struct ClipResult
|
||||
{
|
||||
std::vector<CutIsland> cut_islands;
|
||||
Transform3d trafo; // this rotates the cut into world coords
|
||||
};
|
||||
std::optional<ClipResult> m_result; // the cut plane
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -121,6 +136,9 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
static void line_from_mouse_pos_static(const Vec2d &mouse_pos, const Transform3d &trafo,
|
||||
const Camera &camera, Vec3d &point, Vec3d &direction);
|
||||
|
||||
void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||
Vec3d& point, Vec3d& direction) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -127,32 +127,8 @@ namespace GUI {
|
|||
json j = json::parse(strInput);
|
||||
|
||||
wxString strCmd = j["command"];
|
||||
|
||||
if (strCmd == "request_model_download") {
|
||||
|
||||
std::string model_id = "";
|
||||
if (j["data"].contains("download_url"))
|
||||
model_id = j["data"]["model_id"].get<std::string>();
|
||||
|
||||
std::string profile_id = "";
|
||||
if (j["data"].contains("profile_id"))
|
||||
profile_id = j["data"]["profile_id"].get<std::string>();
|
||||
|
||||
std::string download_url = "";
|
||||
if (j["data"].contains("download_url"))
|
||||
download_url = j["data"]["download_url"].get<std::string>();
|
||||
|
||||
std::string filename = "";
|
||||
if (j["data"].contains("filename"))
|
||||
filename = j["data"]["filename"].get<std::string>();
|
||||
|
||||
if (download_url.empty()) return;
|
||||
|
||||
wxGetApp().set_download_model_url(download_url);
|
||||
wxGetApp().set_download_model_name(filename);
|
||||
wxGetApp().plater()->request_model_download();
|
||||
}
|
||||
else if(strCmd == "request_close_publish_window") {
|
||||
|
||||
if(strCmd == "request_close_publish_window") {
|
||||
this->Hide();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -514,6 +514,24 @@ void MonitorPanel::show_status(int status)
|
|||
|
||||
if (last_status == status)
|
||||
return;
|
||||
|
||||
if (last_status & (int)MonitorStatus::MONITOR_CONNECTING != 0) {
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
json j;
|
||||
j["dev_id"] = obj ? obj->dev_id : "obj_nullptr";
|
||||
if (status & (int)MonitorStatus::MONITOR_DISCONNECTED != 0) {
|
||||
j["result"] = "failed";
|
||||
if (agent) {
|
||||
agent->track_event("connect_dev", j.dump());
|
||||
}
|
||||
}
|
||||
else if (status & (int)MonitorStatus::MONITOR_NORMAL != 0) {
|
||||
j["result"] = "success";
|
||||
if (agent) {
|
||||
agent->track_event("connect_dev", j.dump());
|
||||
}
|
||||
}
|
||||
}
|
||||
last_status = status;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "monitor: show_status = " << status;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he
|
|||
for (auto mb : m_buttons) { delete mb.second->buttondata ; delete mb.second; }
|
||||
}
|
||||
|
||||
void MsgDialog::show_dsa_button()
|
||||
void MsgDialog::show_dsa_button(wxString const &title)
|
||||
{
|
||||
m_checkbox_dsa = new CheckBox(this);
|
||||
m_dsa_sizer->Add(m_checkbox_dsa, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
|
||||
|
|
@ -86,7 +86,7 @@ void MsgDialog::show_dsa_button()
|
|||
e.Skip();
|
||||
});
|
||||
|
||||
auto m_text_dsa = new wxStaticText(this, wxID_ANY, _L("Don't show again"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
auto m_text_dsa = new wxStaticText(this, wxID_ANY, title.IsEmpty() ? _L("Don't show again") : title, wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_dsa_sizer->Add(m_text_dsa, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
|
||||
m_text_dsa->SetFont(::Label::Body_13);
|
||||
m_text_dsa->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3D")));
|
||||
|
|
@ -136,7 +136,7 @@ void MsgDialog::SetButtonLabel(wxWindowID btn_id, const wxString& label, bool se
|
|||
|
||||
Button* MsgDialog::add_button(wxWindowID btn_id, bool set_focus /*= false*/, const wxString& label/* = wxString()*/)
|
||||
{
|
||||
Button* btn = new Button(this, label);
|
||||
Button* btn = new Button(this, label, "", 0, 0, btn_id);
|
||||
ButtonSizeType type;
|
||||
|
||||
if (label.length() < 5) {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ struct MsgDialog : DPIDialog
|
|||
MsgDialog &operator=(const MsgDialog &) = delete;
|
||||
virtual ~MsgDialog();
|
||||
|
||||
void show_dsa_button();
|
||||
void show_dsa_button(wxString const & title = {});
|
||||
bool get_checkbox_state();
|
||||
virtual void on_dpi_changed(const wxRect& suggested_rect);
|
||||
void SetButtonLabel(wxWindowID btn_id, const wxString& label, bool set_focus = false);
|
||||
|
|
|
|||
|
|
@ -861,7 +861,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW
|
|||
ImGui::PushStyleColor(ImGuiCol_Border, { 0,0,0,0 });
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8 * scale, 1 * scale });
|
||||
ImGui::BeginTooltip();
|
||||
imgui.text(_u8L("Safely remove hardware."));
|
||||
imgui.text(_L("Safely remove hardware."));
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleVar();
|
||||
|
|
@ -1020,6 +1020,7 @@ void NotificationManager::UpdatedItemsInfoNotification::add_type(InfoItemType ty
|
|||
case InfoItemType::MmuSegmentation: text += format(_L_PLURAL("%1$d Object has color painting.", "%1$d Objects have color painting.",(*it).second), (*it).second) + "\n"; break;
|
||||
// BBS
|
||||
//case InfoItemType::Sinking: text += format(("%1$d Object has partial sinking.", "%1$d Objects have partial sinking.", (*it).second), (*it).second) + "\n"; break;
|
||||
case InfoItemType::CutConnectors: text += format(_L_PLURAL("%1$d object was loaded as a part of cut object.", "%1$d objects were loaded as parts of cut object", (*it).second), (*it).second) + "\n"; break;
|
||||
default: BOOST_LOG_TRIVIAL(error) << "Unknown InfoItemType: " << (*it).second; break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1111,13 +1112,14 @@ void NotificationManager::PrintHostUploadNotification::render_bar(ImGuiWrapper&
|
|||
}
|
||||
void NotificationManager::PrintHostUploadNotification::render_left_sign(ImGuiWrapper& imgui)
|
||||
{
|
||||
if (m_uj_state == UploadJobState::PB_ERROR) {
|
||||
std::string text;
|
||||
text = ImGui::ErrorMarker;
|
||||
ImGui::SetCursorPosX(m_line_height / 3);
|
||||
ImGui::SetCursorPosY(m_window_height / 2 - m_line_height);
|
||||
imgui.text(text.c_str());
|
||||
}
|
||||
// BBS: do not render left button
|
||||
//if (m_uj_state == UploadJobState::PB_ERROR) {
|
||||
// std::string text;
|
||||
// text = ImGui::ErrorMarker;
|
||||
// ImGui::SetCursorPosX(m_line_height / 3);
|
||||
// ImGui::SetCursorPosY(m_window_height / 2 - m_line_height);
|
||||
// imgui.text(text.c_str());
|
||||
//}
|
||||
}
|
||||
void NotificationManager::PrintHostUploadNotification::render_cancel_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ static constexpr char LayerRootIcon[] = "blank";
|
|||
static constexpr char LayerIcon[] = "blank";
|
||||
static constexpr char WarningIcon[] = "obj_warning";
|
||||
static constexpr char WarningManifoldIcon[] = "obj_warning";
|
||||
static constexpr char LockIcon[] = "cut_";
|
||||
|
||||
ObjectDataViewModelNode::ObjectDataViewModelNode(PartPlate* part_plate, wxString name) :
|
||||
m_parent(nullptr),
|
||||
|
|
@ -65,6 +66,7 @@ const std::map<InfoItemType, InfoItemAtributes> INFO_ITEMS{
|
|||
//{ InfoItemType::CustomSeam, {L("Paint-on seam"), "seam_" }, },
|
||||
{ InfoItemType::MmuSegmentation, {L("Color painting"), "mmu_segmentation"}, },
|
||||
//{ InfoItemType::Sinking, {L("Sinking"), "objlist_sinking"}, },
|
||||
{ InfoItemType::CutConnectors, {L("Cut connectors"), "cut_connectors" }, },
|
||||
};
|
||||
|
||||
ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
|
||||
|
|
@ -222,6 +224,15 @@ void ObjectDataViewModelNode::set_support_icon(bool enable)
|
|||
m_support_icon = create_scaled_bitmap("dot");
|
||||
}
|
||||
|
||||
void ObjectDataViewModelNode::set_sinking_icon(bool enable)
|
||||
{
|
||||
m_sink_enable = enable;
|
||||
if ((m_type & itObject) && enable)
|
||||
m_sinking_icon = create_scaled_bitmap("objlist_sinking");
|
||||
else
|
||||
m_sinking_icon = create_scaled_bitmap("dot");
|
||||
}
|
||||
|
||||
void ObjectDataViewModelNode::set_warning_icon(const std::string& warning_icon_name)
|
||||
{
|
||||
m_warning_icon_name = warning_icon_name;
|
||||
|
|
@ -302,6 +313,9 @@ bool ObjectDataViewModelNode::SetValue(const wxVariant& variant, unsigned col)
|
|||
case colSupportPaint:
|
||||
m_support_icon << variant;
|
||||
break;
|
||||
case colSinking:
|
||||
m_sinking_icon << variant;
|
||||
break;
|
||||
case colColorPaint:
|
||||
m_color_icon << variant;
|
||||
break;
|
||||
|
|
@ -399,6 +413,7 @@ ObjectDataViewModel::ObjectDataViewModel()
|
|||
m_volume_bmps = MenuFactory::get_volume_bitmaps();
|
||||
m_warning_bmp = create_scaled_bitmap(WarningIcon);
|
||||
m_warning_manifold_bmp = create_scaled_bitmap(WarningManifoldIcon);
|
||||
m_lock_bmp = create_scaled_bitmap(LockIcon);
|
||||
|
||||
for (auto item : INFO_ITEMS)
|
||||
m_info_bmps[item.first] = create_scaled_bitmap(item.second.bmp_name);
|
||||
|
|
@ -478,7 +493,47 @@ wxDataViewItem ObjectDataViewModel::AddOutsidePlate(bool refresh)
|
|||
return plate_item;
|
||||
}
|
||||
|
||||
wxDataViewItem ObjectDataViewModel::AddObject(ModelObject* model_object, std::string warning_bitmap, bool refresh)
|
||||
void ObjectDataViewModel::UpdateBitmapForNode(ObjectDataViewModelNode *node)
|
||||
{
|
||||
bool is_volume_node = node->GetType() & itVolume;
|
||||
int vol_type = static_cast<int>(node->GetVolumeType());
|
||||
is_volume_node &= (vol_type >= int(ModelVolumeType::MODEL_PART) && vol_type <= int(ModelVolumeType::SUPPORT_ENFORCER));
|
||||
|
||||
if (!node->has_warning_icon() && !node->has_lock()) {
|
||||
node->SetBitmap(is_volume_node ? m_volume_bmps.at(vol_type) : m_empty_bmp);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string scaled_bitmap_name = std::string();
|
||||
if (node->has_warning_icon())
|
||||
scaled_bitmap_name += node->warning_icon_name();
|
||||
if (node->has_lock())
|
||||
scaled_bitmap_name += LockIcon;
|
||||
if (is_volume_node)
|
||||
scaled_bitmap_name += std::to_string(vol_type);
|
||||
|
||||
wxBitmap *bmp = m_bitmap_cache->find(scaled_bitmap_name);
|
||||
if (!bmp) {
|
||||
std::vector<wxBitmap> bmps;
|
||||
if (node->has_warning_icon())
|
||||
bmps.emplace_back(node->warning_icon_name() == WarningIcon ? m_warning_bmp : m_warning_manifold_bmp);
|
||||
if (node->has_lock())
|
||||
bmps.emplace_back(m_lock_bmp);
|
||||
if (is_volume_node)
|
||||
bmps.emplace_back(m_volume_bmps[vol_type]);
|
||||
bmp = m_bitmap_cache->insert(scaled_bitmap_name, bmps);
|
||||
}
|
||||
|
||||
node->SetBitmap(*bmp);
|
||||
}
|
||||
|
||||
void ObjectDataViewModel::UpdateBitmapForNode(ObjectDataViewModelNode *node, bool has_lock)
|
||||
{
|
||||
node->SetLock(has_lock);
|
||||
UpdateBitmapForNode(node);
|
||||
}
|
||||
|
||||
wxDataViewItem ObjectDataViewModel::AddObject(ModelObject *model_object, std::string warning_bitmap, bool has_lock, bool refresh)
|
||||
{
|
||||
// get object node params
|
||||
wxString name = from_u8(model_object->name);
|
||||
|
|
@ -500,6 +555,7 @@ wxDataViewItem ObjectDataViewModel::AddObject(ModelObject* model_object, std::st
|
|||
const wxString extruder_str = wxString::Format("%d", extruder);
|
||||
auto obj_node = new ObjectDataViewModelNode(name, extruder_str, plate_idx, model_object);
|
||||
obj_node->SetWarningBitmap(GetWarningBitmap(warning_bitmap), warning_bitmap);
|
||||
UpdateBitmapForNode(obj_node, has_lock);
|
||||
|
||||
if (plate_node != nullptr) {
|
||||
obj_node->m_parent = plate_node;
|
||||
|
|
@ -1151,7 +1207,7 @@ void ObjectDataViewModel::DeleteSettings(const wxDataViewItem& parent)
|
|||
node->set_action_icon(false);
|
||||
ItemChanged(parent);
|
||||
#else
|
||||
if volume has a "settings"item, than delete it before volume deleting
|
||||
// if volume has a "settings"item, than delete it before volume deleting
|
||||
if (node->GetChildCount() > 0 && node->GetNthChild(0)->GetType() == itSettings) {
|
||||
auto settings_node = node->GetNthChild(0);
|
||||
auto settings_item = wxDataViewItem(settings_node);
|
||||
|
|
@ -1557,6 +1613,9 @@ void ObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem &ite
|
|||
case colSupportPaint:
|
||||
variant << node->m_support_icon;
|
||||
break;
|
||||
case colSinking:
|
||||
variant << node->m_sinking_icon;
|
||||
break;
|
||||
case colColorPaint:
|
||||
variant << node->m_color_icon;
|
||||
break;
|
||||
|
|
@ -2081,6 +2140,14 @@ bool ObjectDataViewModel::IsSupportPainted(wxDataViewItem& item) const
|
|||
return node->m_support_enable;
|
||||
}
|
||||
|
||||
bool ObjectDataViewModel::IsSinked(wxDataViewItem &item) const
|
||||
{
|
||||
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode *>(item.GetID());
|
||||
if (!node) return false;
|
||||
|
||||
return node->m_sink_enable;
|
||||
}
|
||||
|
||||
void ObjectDataViewModel::SetColorPaintState(const bool painted, wxDataViewItem obj_item)
|
||||
{
|
||||
ObjectDataViewModelNode* node = static_cast<ObjectDataViewModelNode*>(obj_item.GetID());
|
||||
|
|
@ -2101,11 +2168,21 @@ void ObjectDataViewModel::SetSupportPaintState(const bool painted, wxDataViewIte
|
|||
ItemChanged(obj_item);
|
||||
}
|
||||
|
||||
void ObjectDataViewModel::SetSinkState(const bool painted, wxDataViewItem obj_item)
|
||||
{
|
||||
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode *>(obj_item.GetID());
|
||||
if (!node) return;
|
||||
|
||||
node->set_sinking_icon(painted);
|
||||
ItemChanged(obj_item);
|
||||
}
|
||||
|
||||
void ObjectDataViewModel::Rescale()
|
||||
{
|
||||
m_volume_bmps = MenuFactory::get_volume_bitmaps();
|
||||
m_warning_bmp = create_scaled_bitmap(WarningIcon);
|
||||
m_warning_manifold_bmp = create_scaled_bitmap(WarningManifoldIcon);
|
||||
m_lock_bmp = create_scaled_bitmap(LockIcon);
|
||||
|
||||
for (auto item : INFO_ITEMS)
|
||||
m_info_bmps[item.first] = create_scaled_bitmap(item.second.bmp_name);
|
||||
|
|
@ -2131,8 +2208,10 @@ void ObjectDataViewModel::Rescale()
|
|||
break;
|
||||
case itLayerRoot:
|
||||
node->m_bmp = create_scaled_bitmap(LayerRootIcon);
|
||||
break;
|
||||
case itLayer:
|
||||
node->m_bmp = create_scaled_bitmap(LayerIcon);
|
||||
break;
|
||||
case itInfo:
|
||||
node->m_bmp = m_info_bmps.at(node->m_info_item_type);
|
||||
break;
|
||||
|
|
@ -2224,6 +2303,26 @@ void ObjectDataViewModel::UpdateWarningIcon(const wxDataViewItem& item, const st
|
|||
AddWarningIcon(item, warning_icon_name);
|
||||
}
|
||||
|
||||
void ObjectDataViewModel::UpdateCutObjectIcon(const wxDataViewItem &item, bool has_lock)
|
||||
{
|
||||
if (!item.IsOk())
|
||||
return;
|
||||
ObjectDataViewModelNode* node = static_cast<ObjectDataViewModelNode*>(item.GetID());
|
||||
if (node->has_lock() == has_lock)
|
||||
return;
|
||||
|
||||
node->SetLock(has_lock);
|
||||
UpdateBitmapForNode(node);
|
||||
|
||||
if (node->GetType() & itObject) {
|
||||
wxDataViewItemArray children;
|
||||
GetChildren(item, children);
|
||||
for (const wxDataViewItem &child : children)
|
||||
UpdateCutObjectIcon(child, has_lock);
|
||||
}
|
||||
ItemChanged(item);
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ enum ColumnNumber
|
|||
// BBS
|
||||
colSupportPaint ,
|
||||
colColorPaint ,
|
||||
colSinking ,
|
||||
colEditing , // item editing
|
||||
colCount ,
|
||||
};
|
||||
|
|
@ -60,6 +61,7 @@ enum class InfoItemType
|
|||
//CustomSeam,
|
||||
MmuSegmentation,
|
||||
//Sinking
|
||||
CutConnectors,
|
||||
};
|
||||
|
||||
class ObjectDataViewModelNode;
|
||||
|
|
@ -87,9 +89,11 @@ class ObjectDataViewModelNode
|
|||
// BBS
|
||||
wxBitmap m_support_icon;
|
||||
wxBitmap m_color_icon;
|
||||
wxBitmap m_sinking_icon;
|
||||
PrintIndicator m_printable {piUndef};
|
||||
wxBitmap m_printable_icon;
|
||||
std::string m_warning_icon_name{ "" };
|
||||
bool m_has_lock{false}; // for cut object icon
|
||||
|
||||
std::string m_action_icon_name = "";
|
||||
ModelVolumeType m_volume_type;
|
||||
|
|
@ -98,6 +102,7 @@ class ObjectDataViewModelNode
|
|||
// BBS
|
||||
bool m_support_enable = false;
|
||||
bool m_color_enable = false;
|
||||
bool m_sink_enable = false;
|
||||
|
||||
public:
|
||||
PartPlate* m_part_plate;
|
||||
|
|
@ -221,6 +226,7 @@ public:
|
|||
void SetBitmap(const wxBitmap &icon) { m_bmp = icon; }
|
||||
void SetExtruder(const wxString &extruder) { m_extruder = extruder; }
|
||||
void SetWarningBitmap(const wxBitmap& icon, const std::string& warning_icon_name) { m_bmp = icon; m_warning_icon_name = warning_icon_name; }
|
||||
void SetLock(bool has_lock) { m_has_lock = has_lock; }
|
||||
const wxBitmap& GetBitmap() const { return m_bmp; }
|
||||
const wxString& GetName() const { return m_name; }
|
||||
ItemType GetType() const { return m_type; }
|
||||
|
|
@ -236,7 +242,8 @@ public:
|
|||
PrintIndicator IsPrintable() const { return m_printable; }
|
||||
// BBS
|
||||
bool HasColorPainting() const { return m_color_enable; }
|
||||
bool HasSupportPainting() const { return m_support_enable; }
|
||||
bool HasSupportPainting() const { return m_support_enable; }
|
||||
bool HasSinking() const { return m_sink_enable; }
|
||||
bool IsActionEnabled() const { return m_action_enable; }
|
||||
void UpdateExtruderAndColorIcon(wxString extruder = "");
|
||||
|
||||
|
|
@ -278,6 +285,7 @@ public:
|
|||
// BBS
|
||||
void set_color_icon(bool enable);
|
||||
void set_support_icon(bool enable);
|
||||
void set_sinking_icon(bool enable);
|
||||
|
||||
// Set warning icon for node
|
||||
void set_warning_icon(const std::string& warning_icon);
|
||||
|
|
@ -292,6 +300,8 @@ public:
|
|||
#endif /* NDEBUG */
|
||||
bool invalid() const { return m_idx < -1; }
|
||||
bool has_warning_icon() const { return !m_warning_icon_name.empty(); }
|
||||
std::string warning_icon_name() const { return m_warning_icon_name; }
|
||||
bool has_lock() const { return m_has_lock; }
|
||||
|
||||
private:
|
||||
friend class ObjectDataViewModel;
|
||||
|
|
@ -314,6 +324,7 @@ class ObjectDataViewModel :public wxDataViewModel
|
|||
wxBitmap m_empty_bmp;
|
||||
wxBitmap m_warning_bmp;
|
||||
wxBitmap m_warning_manifold_bmp;
|
||||
wxBitmap m_lock_bmp;
|
||||
|
||||
ObjectDataViewModelNode* m_plate_outside;
|
||||
|
||||
|
|
@ -325,7 +336,7 @@ public:
|
|||
void Init();
|
||||
|
||||
wxDataViewItem AddPlate(PartPlate* part_plate, wxString name = wxEmptyString, bool refresh = true);
|
||||
wxDataViewItem AddObject(ModelObject* model_object, std::string warning_bitmap, bool refresh = true);
|
||||
wxDataViewItem AddObject(ModelObject* model_object, std::string warning_bitmap, bool has_lock = false, bool refresh = true);
|
||||
wxDataViewItem AddVolumeChild( const wxDataViewItem &parent_item,
|
||||
const wxString &name,
|
||||
const Slic3r::ModelVolumeType volume_type,
|
||||
|
|
@ -442,9 +453,11 @@ public:
|
|||
wxDataViewItem SetObjectPrintableState(PrintIndicator printable, wxDataViewItem obj_item);
|
||||
// BBS
|
||||
bool IsColorPainted(wxDataViewItem& item) const;
|
||||
bool IsSupportPainted(wxDataViewItem& item) const;
|
||||
bool IsSupportPainted(wxDataViewItem &item) const;
|
||||
bool IsSinked(wxDataViewItem &item) const;
|
||||
void SetColorPaintState(const bool painted, wxDataViewItem obj_item);
|
||||
void SetSupportPaintState(const bool painted, wxDataViewItem obj_item);
|
||||
void SetSinkState(const bool painted, wxDataViewItem obj_item);
|
||||
|
||||
void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
|
||||
// Rescale bitmaps for existing Items
|
||||
|
|
@ -455,6 +468,7 @@ public:
|
|||
void AddWarningIcon(const wxDataViewItem& item, const std::string& warning_name);
|
||||
void DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false);
|
||||
void UpdateWarningIcon(const wxDataViewItem& item, const std::string& warning_name);
|
||||
void UpdateCutObjectIcon(const wxDataViewItem &item, bool has_cut_icon);
|
||||
bool HasWarningIcon(const wxDataViewItem& item) const;
|
||||
t_layer_height_range GetLayerRangeByItem(const wxDataViewItem& item) const;
|
||||
|
||||
|
|
@ -475,6 +489,9 @@ private:
|
|||
wxBitmap& GetWarningBitmap(const std::string& warning_icon_name);
|
||||
void ReparentObject(ObjectDataViewModelNode* plate, ObjectDataViewModelNode* object);
|
||||
wxDataViewItem AddOutsidePlate(bool refresh = true);
|
||||
|
||||
void UpdateBitmapForNode(ObjectDataViewModelNode *node);
|
||||
void UpdateBitmapForNode(ObjectDataViewModelNode *node, bool has_lock);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -251,14 +251,19 @@ bool OpenGLManager::init_gl()
|
|||
if (GLEW_ARB_framebuffer_object) {
|
||||
s_framebuffers_type = EFramebufferType::Arb;
|
||||
BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type ARB."<< std::endl;
|
||||
}
|
||||
else if (GLEW_EXT_framebuffer_object)
|
||||
}
|
||||
else if (GLEW_EXT_framebuffer_object) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type Ext."<< std::endl;
|
||||
s_framebuffers_type = EFramebufferType::Ext;
|
||||
else
|
||||
}
|
||||
else {
|
||||
s_framebuffers_type = EFramebufferType::Unknown;
|
||||
BOOST_LOG_TRIVIAL(warning) << "Found Framebuffer Type unknown!"<< std::endl;
|
||||
}
|
||||
|
||||
bool valid_version = s_gl_info.is_version_greater_or_equal_to(2, 0);
|
||||
if (!valid_version) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Found opengl version <= 2.0"<< std::endl;
|
||||
// Complain about the OpenGL version.
|
||||
wxString message = from_u8((boost::format(
|
||||
_utf8(L("The application cannot run normally because OpenGL version is lower than 2.0.\n")))).str());
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ void OptionsGroup::activate_line(Line& line)
|
|||
const auto h_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(h_sizer, 1, wxEXPAND | wxALL, wxOSX ? 0 : 5);
|
||||
if (is_window_field(field))
|
||||
h_sizer->Add(field->getWindow(), 1, wxEXPAND | wxLEFT, titleWidth * wxGetApp().em_unit());
|
||||
h_sizer->Add(field->getWindow(), 1, wxEXPAND | wxLEFT, option.opt.multiline ? 0 : titleWidth * wxGetApp().em_unit());
|
||||
if (is_sizer_field(field))
|
||||
h_sizer->Add(field->getSizer(), 1, wxEXPAND | wxLEFT, titleWidth * wxGetApp().em_unit());
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -404,6 +404,10 @@ void ParamsPanel::create_layout()
|
|||
m_left_sizer->Add( m_tab_print_part, 0, wxEXPAND );
|
||||
}
|
||||
|
||||
if (m_tab_print_layer) {
|
||||
m_left_sizer->Add(m_tab_print_layer, 0, wxEXPAND);
|
||||
}
|
||||
|
||||
if (m_tab_filament) {
|
||||
if (m_staticline_filament)
|
||||
m_left_sizer->Add(m_staticline_filament, 0, wxEXPAND);
|
||||
|
|
@ -488,6 +492,7 @@ void ParamsPanel::refresh_tabs()
|
|||
if (m_top_panel) {
|
||||
m_tab_print_object = wxGetApp().get_model_tab();
|
||||
m_tab_print_part = wxGetApp().get_model_tab(true);
|
||||
m_tab_print_layer = wxGetApp().get_layer_tab();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -557,6 +562,8 @@ void ParamsPanel::set_active_tab(wxPanel* tab)
|
|||
cur_tab = (Tab*) m_tab_print;
|
||||
} else if (m_tab_print_part && ((TabPrintModel*) m_tab_print_part)->has_model_config()) {
|
||||
cur_tab = (Tab*) m_tab_print_part;
|
||||
} else if (m_tab_print_layer && ((TabPrintModel*)m_tab_print_layer)->has_model_config()) {
|
||||
cur_tab = (Tab*)m_tab_print_layer;
|
||||
} else if (m_tab_print_object && ((TabPrintModel*) m_tab_print_object)->has_model_config()) {
|
||||
cur_tab = (Tab*) m_tab_print_object;
|
||||
}
|
||||
|
|
@ -578,6 +585,7 @@ void ParamsPanel::set_active_tab(wxPanel* tab)
|
|||
{m_tab_print, m_staticline_print},
|
||||
{m_tab_print_object, m_staticline_print_object},
|
||||
{m_tab_print_part, m_staticline_print_part},
|
||||
{m_tab_print_layer, nullptr},
|
||||
{m_tab_filament, m_staticline_filament},
|
||||
{m_tab_printer, m_staticline_printer}})) {
|
||||
if (!t.first) continue;
|
||||
|
|
@ -650,7 +658,7 @@ void ParamsPanel::msw_rescale()
|
|||
((SwitchButton* )m_mode_region)->Rescale();
|
||||
if (m_mode_view)
|
||||
((SwitchButton* )m_mode_view)->Rescale();
|
||||
for (auto tab : {m_tab_print, m_tab_print_object, m_tab_print_part, m_tab_filament, m_tab_printer}) {
|
||||
for (auto tab : {m_tab_print, m_tab_print_object, m_tab_print_part, m_tab_print_layer, m_tab_filament, m_tab_printer}) {
|
||||
if (tab) dynamic_cast<Tab*>(tab)->msw_rescale();
|
||||
}
|
||||
//((Button*)m_export_to_file)->Rescale();
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ class ParamsPanel : public wxPanel
|
|||
wxPanel* m_tab_print_object { nullptr };
|
||||
wxStaticLine* m_staticline_print_object { nullptr };
|
||||
wxPanel* m_tab_print_part { nullptr };
|
||||
wxPanel* m_tab_print_layer { nullptr };
|
||||
wxStaticLine* m_staticline_print_part { nullptr };
|
||||
wxStaticLine* m_staticline_filament { nullptr };
|
||||
//wxBoxSizer* m_filament_sizer { nullptr };
|
||||
|
|
|
|||
|
|
@ -171,17 +171,21 @@ void PartPlate::init()
|
|||
m_plate_name_vbo_id = 0;
|
||||
}
|
||||
|
||||
BedType PartPlate::get_bed_type() const
|
||||
BedType PartPlate::get_bed_type(bool load_from_project) const
|
||||
{
|
||||
std::string bed_type_key = "curr_bed_type";
|
||||
|
||||
// should be called in GUI context
|
||||
assert(m_plater != nullptr);
|
||||
if (m_config.has(bed_type_key)) {
|
||||
BedType bed_type = m_config.opt_enum<BedType>(bed_type_key);
|
||||
return bed_type;
|
||||
}
|
||||
|
||||
if (!load_from_project || !m_plater || !wxGetApp().preset_bundle)
|
||||
return btDefault;
|
||||
|
||||
DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
|
||||
if (proj_cfg.has(bed_type_key))
|
||||
return proj_cfg.opt_enum<BedType>(bed_type_key);
|
||||
return btDefault;
|
||||
}
|
||||
|
||||
|
|
@ -258,9 +262,6 @@ PrintSequence PartPlate::get_print_seq() const
|
|||
{
|
||||
std::string print_seq_key = "print_sequence";
|
||||
|
||||
// should be called in GUI context
|
||||
assert(m_plater != nullptr);
|
||||
|
||||
if (m_config.has(print_seq_key)) {
|
||||
PrintSequence print_seq = m_config.opt_enum<PrintSequence>(print_seq_key);
|
||||
return print_seq;
|
||||
|
|
@ -1344,10 +1345,14 @@ std::vector<int> PartPlate::get_extruders(bool conside_custom_gcode) const
|
|||
|
||||
if (conside_custom_gcode) {
|
||||
//BBS
|
||||
if (m_model->plates_custom_gcodes.find(m_plate_index) != m_model->plates_custom_gcodes.end()) {
|
||||
for (auto item : m_model->plates_custom_gcodes.at(m_plate_index).gcodes) {
|
||||
if (item.type == CustomGCode::Type::ToolChange)
|
||||
plate_extruders.push_back(item.extruder);
|
||||
int nums_extruders = 0;
|
||||
if (const ConfigOptionStrings *color_option = dynamic_cast<const ConfigOptionStrings *>(wxGetApp().preset_bundle->project_config.option("filament_colour"))) {
|
||||
nums_extruders = color_option->values.size();
|
||||
if (m_model->plates_custom_gcodes.find(m_plate_index) != m_model->plates_custom_gcodes.end()) {
|
||||
for (auto item : m_model->plates_custom_gcodes.at(m_plate_index).gcodes) {
|
||||
if (item.type == CustomGCode::Type::ToolChange && item.extruder <= nums_extruders)
|
||||
plate_extruders.push_back(item.extruder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1731,6 +1736,8 @@ bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* boundi
|
|||
m_origin.z() + m_height + Slic3r::BuildVolume::SceneEpsilon);
|
||||
Vec3d low_point = m_bounding_box.min + Vec3d(-Slic3r::BuildVolume::SceneEpsilon, -Slic3r::BuildVolume::SceneEpsilon,
|
||||
m_origin.z() - Slic3r::BuildVolume::SceneEpsilon);
|
||||
Polygon hull = instance->convex_hull_2d();
|
||||
if (instance_box.max.z() > low_point.z()) low_point.z() += instance_box.min.z(); // not considering outsize if sinking
|
||||
BoundingBoxf3 plate_box(low_point, up_point);
|
||||
|
||||
if (plate_box.contains(instance_box))
|
||||
|
|
@ -2449,21 +2456,26 @@ int PartPlate::load_gcode_from_file(const std::string& filename)
|
|||
// BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("Failed to rename the output G-code file from %1% to %2%, error code %3%") % filename.c_str() % path.c_str() %
|
||||
//error.message(); return -1;
|
||||
//}
|
||||
if (boost::filesystem::exists(filename)) {
|
||||
assert(m_tmp_gcode_path.empty());
|
||||
m_tmp_gcode_path = filename;
|
||||
m_gcode_result->filename = filename;
|
||||
m_print->set_gcode_file_ready();
|
||||
if (boost::filesystem::exists(filename)) {
|
||||
assert(m_tmp_gcode_path.empty());
|
||||
m_tmp_gcode_path = filename;
|
||||
m_gcode_result->filename = filename;
|
||||
m_print->set_gcode_file_ready();
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": from %1% to %2%, finished") % filename.c_str() % filename.c_str();
|
||||
}
|
||||
update_slice_result_valid_state(true);
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": found valid gcode file %1%") % filename.c_str();
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": can not find gcode file %1%") % filename.c_str();
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
update_slice_result_valid_state(true);
|
||||
m_ready_for_slice = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PartPlate::load_thumbnail_data(std::string filename)
|
||||
int PartPlate::load_thumbnail_data(std::string filename, ThumbnailData& thumb_data)
|
||||
{
|
||||
bool result = true;
|
||||
wxImage img;
|
||||
|
|
@ -2472,11 +2484,11 @@ int PartPlate::load_thumbnail_data(std::string filename)
|
|||
img = img.Mirror(false);
|
||||
}
|
||||
if (result) {
|
||||
thumbnail_data.set(img.GetWidth(), img.GetHeight());
|
||||
thumb_data.set(img.GetWidth(), img.GetHeight());
|
||||
for (int i = 0; i < img.GetWidth() * img.GetHeight(); i++) {
|
||||
memcpy(&thumbnail_data.pixels[4 * i], (unsigned char*)(img.GetData() + 3 * i), 3);
|
||||
memcpy(&thumb_data.pixels[4 * i], (unsigned char*)(img.GetData() + 3 * i), 3);
|
||||
if (img.HasAlpha()) {
|
||||
thumbnail_data.pixels[4 * i + 3] = *(unsigned char*)(img.GetAlpha() + i);
|
||||
thumb_data.pixels[4 * i + 3] = *(unsigned char*)(img.GetAlpha() + i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -2487,7 +2499,7 @@ int PartPlate::load_thumbnail_data(std::string filename)
|
|||
|
||||
int PartPlate::load_pattern_thumbnail_data(std::string filename)
|
||||
{
|
||||
bool result = true;
|
||||
/*bool result = true;
|
||||
wxImage img;
|
||||
result = load_image(filename, img);
|
||||
if (result) {
|
||||
|
|
@ -2501,7 +2513,7 @@ int PartPlate::load_pattern_thumbnail_data(std::string filename)
|
|||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3520,6 +3532,8 @@ int PartPlateList::notify_instance_update(int obj_id, int instance_id)
|
|||
PartPlate* plate = m_plate_list[obj_id - 1000];
|
||||
plate->update_slice_result_valid_state( false );
|
||||
plate->thumbnail_data.reset();
|
||||
plate->top_thumbnail_data.reset();
|
||||
plate->pick_thumbnail_data.reset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3548,10 +3562,14 @@ int PartPlateList::notify_instance_update(int obj_id, int instance_id)
|
|||
plate->update_states();
|
||||
plate->update_slice_result_valid_state();
|
||||
plate->thumbnail_data.reset();
|
||||
plate->top_thumbnail_data.reset();
|
||||
plate->pick_thumbnail_data.reset();
|
||||
return 0;
|
||||
}
|
||||
plate->update_slice_result_valid_state();
|
||||
plate->thumbnail_data.reset();
|
||||
plate->top_thumbnail_data.reset();
|
||||
plate->pick_thumbnail_data.reset();
|
||||
}
|
||||
else if (unprintable_plate.contain_instance(obj_id, instance_id))
|
||||
{
|
||||
|
|
@ -3582,6 +3600,8 @@ int PartPlateList::notify_instance_update(int obj_id, int instance_id)
|
|||
plate->add_instance(obj_id, instance_id, false, &boundingbox);
|
||||
plate->update_slice_result_valid_state();
|
||||
plate->thumbnail_data.reset();
|
||||
plate->top_thumbnail_data.reset();
|
||||
plate->pick_thumbnail_data.reset();
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": add it to new plate %1%") % i;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3617,6 +3637,8 @@ int PartPlateList::notify_instance_removed(int obj_id, int instance_id)
|
|||
plate->remove_instance(obj_id, instance_to_delete);
|
||||
plate->update_slice_result_valid_state();
|
||||
plate->thumbnail_data.reset();
|
||||
plate->top_thumbnail_data.reset();
|
||||
plate->pick_thumbnail_data.reset();
|
||||
}
|
||||
|
||||
if (unprintable_plate.contain_instance(obj_id, instance_to_delete))
|
||||
|
|
@ -4058,7 +4080,7 @@ void PartPlateList::postprocess_arrange_polygon(arrangement::ArrangePolygon& arr
|
|||
{
|
||||
// outarea for large object
|
||||
arrange_polygon.bed_idx = m_plate_list.size();
|
||||
BoundingBox apbox(arrange_polygon.poly);
|
||||
BoundingBox apbox = get_extents(arrange_polygon.poly);
|
||||
auto apbox_size = apbox.size();
|
||||
|
||||
//arrange_polygon.translation(X) = scaled<double>(0.5 * plate_stride_x());
|
||||
|
|
@ -4512,6 +4534,11 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w
|
|||
%(i+1) %plate_data_item->plate_thumbnail.width %plate_data_item->plate_thumbnail.height %plate_data_item->plate_thumbnail.pixels.size();
|
||||
plate_data_item->config.apply(*m_plate_list[i]->config());
|
||||
|
||||
if (m_plate_list[i]->top_thumbnail_data.is_valid())
|
||||
plate_data_item->top_file = "valid_top";
|
||||
if (m_plate_list[i]->pick_thumbnail_data.is_valid())
|
||||
plate_data_item->pick_file = "valid_pick";
|
||||
|
||||
if (m_plate_list[i]->obj_to_instance_set.size() > 0)
|
||||
{
|
||||
for (std::set<std::pair<int, int>>::iterator it = m_plate_list[i]->obj_to_instance_set.begin(); it != m_plate_list[i]->obj_to_instance_set.end(); ++it)
|
||||
|
|
@ -4526,8 +4553,8 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w
|
|||
// BBS only include current palte_idx
|
||||
if (plate_idx == i || plate_idx == PLATE_CURRENT_IDX || plate_idx == PLATE_ALL_IDX) {
|
||||
//load calibration thumbnail
|
||||
if (m_plate_list[i]->cali_thumbnail_data.is_valid())
|
||||
plate_data_item->pattern_file = "valid_pattern";
|
||||
//if (m_plate_list[i]->cali_thumbnail_data.is_valid())
|
||||
// plate_data_item->pattern_file = "valid_pattern";
|
||||
if (m_plate_list[i]->cali_bboxes_data.is_valid())
|
||||
plate_data_item->pattern_bbox_file = "valid_pattern_bbox";
|
||||
plate_data_item->gcode_file = m_plate_list[i]->m_gcode_result->filename;
|
||||
|
|
@ -4610,17 +4637,29 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list)
|
|||
if (m_plater && !plate_data_list[i]->thumbnail_file.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load thumbnail from %2%.")%(i+1) %plate_data_list[i]->thumbnail_file;
|
||||
if (boost::filesystem::exists(plate_data_list[i]->thumbnail_file)) {
|
||||
m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->thumbnail_file);
|
||||
m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->thumbnail_file, m_plate_list[index]->thumbnail_data);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <<boost::format(": plate %1% after load, width %2%, height %3%, size %4%!")
|
||||
%(i+1) %m_plate_list[index]->thumbnail_data.width %m_plate_list[index]->thumbnail_data.height %m_plate_list[index]->thumbnail_data.pixels.size();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_plater && !plate_data_list[i]->pattern_file.empty()) {
|
||||
/*if (m_plater && !plate_data_list[i]->pattern_file.empty()) {
|
||||
if (boost::filesystem::exists(plate_data_list[i]->pattern_file)) {
|
||||
//no need to load pattern data currently
|
||||
//m_plate_list[index]->load_pattern_thumbnail_data(plate_data_list[i]->pattern_file);
|
||||
}
|
||||
}*/
|
||||
if (m_plater && !plate_data_list[i]->top_file.empty()) {
|
||||
if (boost::filesystem::exists(plate_data_list[i]->top_file)) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load top_thumbnail from %2%.")%(i+1) %plate_data_list[i]->top_file;
|
||||
m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->top_file, m_plate_list[index]->top_thumbnail_data);
|
||||
}
|
||||
}
|
||||
if (m_plater && !plate_data_list[i]->pick_file.empty()) {
|
||||
if (boost::filesystem::exists(plate_data_list[i]->pick_file)) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load pick_thumbnail from %2%.")%(i+1) %plate_data_list[i]->pick_file;
|
||||
m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->pick_file, m_plate_list[index]->pick_thumbnail_data);
|
||||
}
|
||||
}
|
||||
if (m_plater && !plate_data_list[i]->pattern_bbox_file.empty()) {
|
||||
if (boost::filesystem::exists(plate_data_list[i]->pattern_bbox_file)) {
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ public:
|
|||
//clear alll the instances in plate
|
||||
void clear(bool clear_sliced_result = true);
|
||||
|
||||
BedType get_bed_type() const;
|
||||
BedType get_bed_type(bool load_from_project = false) const;
|
||||
void set_bed_type(BedType bed_type);
|
||||
void reset_bed_type();
|
||||
DynamicPrintConfig* config() { return &m_config; }
|
||||
|
|
@ -243,10 +243,13 @@ public:
|
|||
static const int plate_thumbnail_width = 512;
|
||||
static const int plate_thumbnail_height = 512;
|
||||
|
||||
ThumbnailData cali_thumbnail_data;
|
||||
ThumbnailData top_thumbnail_data;
|
||||
ThumbnailData pick_thumbnail_data;
|
||||
|
||||
//ThumbnailData cali_thumbnail_data;
|
||||
PlateBBoxData cali_bboxes_data;
|
||||
static const int cali_thumbnail_width = 2560;
|
||||
static const int cali_thumbnail_height = 2560;
|
||||
//static const int cali_thumbnail_width = 2560;
|
||||
//static const int cali_thumbnail_height = 2560;
|
||||
|
||||
//set the plate's index
|
||||
void set_index(int index);
|
||||
|
|
@ -397,7 +400,7 @@ public:
|
|||
{
|
||||
bool result = m_slice_result_valid;
|
||||
if (result)
|
||||
result = m_gcode_result ? (!m_gcode_result->toolpath_outside) : false;
|
||||
result = m_gcode_result ? (!m_gcode_result->toolpath_outside && !m_gcode_result->conflict_result.has_value()) : false;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -429,7 +432,7 @@ public:
|
|||
//load gcode from file
|
||||
int load_gcode_from_file(const std::string& filename);
|
||||
//load thumbnail data from file
|
||||
int load_thumbnail_data(std::string filename);
|
||||
int load_thumbnail_data(std::string filename, ThumbnailData& thumb_data);
|
||||
//load pattern thumbnail data from file
|
||||
int load_pattern_thumbnail_data(std::string filename);
|
||||
//load pattern box data from file
|
||||
|
|
|
|||
|
|
@ -325,6 +325,7 @@ struct Sidebar::priv
|
|||
|
||||
ObjectList *m_object_list{ nullptr };
|
||||
ObjectSettings *object_settings{ nullptr };
|
||||
ObjectLayers *object_layers{ nullptr };
|
||||
|
||||
wxButton *btn_export_gcode;
|
||||
wxButton *btn_reslice;
|
||||
|
|
@ -464,7 +465,7 @@ static struct DynamicFilamentList : DynamicList
|
|||
wxString str;
|
||||
std::string type;
|
||||
wxGetApp().preset_bundle->filaments.find_preset(presets[i])->get_filament_type(type);
|
||||
str << (i + 1) << " - " << type;
|
||||
str << type;
|
||||
items.push_back({str, icons[i]});
|
||||
}
|
||||
DynamicList::update();
|
||||
|
|
@ -757,7 +758,6 @@ Sidebar::Sidebar(Plater *parent)
|
|||
(project_config.option<ConfigOptionFloats>("flush_volumes_vector"))->values = std::vector<double>(extruders.begin(), extruders.end());
|
||||
(project_config.option<ConfigOptionFloat>("flush_multiplier"))->set(new ConfigOptionFloat(dlg.get_flush_multiplier()));
|
||||
|
||||
wxGetApp().app_config->set("flush_multiplier", std::to_string(dlg.get_flush_multiplier()));
|
||||
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
|
||||
|
||||
wxGetApp().plater()->update_project_dirty_from_presets();
|
||||
|
|
@ -924,6 +924,10 @@ Sidebar::Sidebar(Plater *parent)
|
|||
#endif
|
||||
}
|
||||
|
||||
p->object_layers = new ObjectLayers(p->scrolled);
|
||||
p->object_layers->Hide();
|
||||
p->sizer_params->Add(p->object_layers->get_sizer(), 0, wxEXPAND | wxTOP, 0);
|
||||
|
||||
auto *sizer = new wxBoxSizer(wxVERTICAL);
|
||||
sizer->Add(p->scrolled, 1, wxEXPAND);
|
||||
SetSizer(sizer);
|
||||
|
|
@ -1285,6 +1289,7 @@ void Sidebar::sys_color_changed()
|
|||
|
||||
// BBS
|
||||
obj_list()->sys_color_changed();
|
||||
obj_layers()->sys_color_changed();
|
||||
// BBS
|
||||
//p->object_manipulation->sys_color_changed();
|
||||
|
||||
|
|
@ -1461,6 +1466,9 @@ void Sidebar::sync_ams_list()
|
|||
wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0]);
|
||||
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
|
||||
dynamic_filament_list.update();
|
||||
// Expand filament list
|
||||
p->m_panel_filament_content->SetMaxSize({-1, -1});
|
||||
Layout();
|
||||
}
|
||||
|
||||
ObjectList* Sidebar::obj_list()
|
||||
|
|
@ -1475,6 +1483,11 @@ ObjectSettings* Sidebar::obj_settings()
|
|||
return p->object_settings;
|
||||
}
|
||||
|
||||
ObjectLayers* Sidebar::obj_layers()
|
||||
{
|
||||
return p->object_layers;
|
||||
}
|
||||
|
||||
wxPanel* Sidebar::scrolled_panel()
|
||||
{
|
||||
return p->scrolled;
|
||||
|
|
@ -1939,7 +1952,7 @@ struct Plater::priv
|
|||
void select_all();
|
||||
void deselect_all();
|
||||
void remove(size_t obj_idx);
|
||||
void delete_object_from_model(size_t obj_idx, bool refresh_immediately = true); //BBS
|
||||
bool delete_object_from_model(size_t obj_idx, bool refresh_immediately = true); //BBS
|
||||
void delete_all_objects_from_model();
|
||||
void reset(bool apply_presets_change = false);
|
||||
void center_selection();
|
||||
|
|
@ -2126,7 +2139,8 @@ struct Plater::priv
|
|||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
//BBS: add plate_id for thumbnail
|
||||
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type);
|
||||
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
|
||||
Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
|
||||
ThumbnailsList generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type);
|
||||
//BBS
|
||||
void generate_calibration_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params);
|
||||
|
|
@ -2456,12 +2470,13 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
plate->update_slice_result_valid_state(false);
|
||||
}
|
||||
}
|
||||
set_plater_dirty(true);
|
||||
|
||||
preview->on_tick_changed(tick_event_type);
|
||||
|
||||
// update slice and print button
|
||||
wxGetApp().mainframe->update_slice_print_status(MainFrame::SlicePrintEventType::eEventSliceUpdate, true, false);
|
||||
set_need_update(true);
|
||||
update();
|
||||
});
|
||||
}
|
||||
if (wxGetApp().is_gcode_viewer())
|
||||
|
|
@ -3266,9 +3281,14 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||
if (!config_substitutions.empty()) show_substitutions_info(config_substitutions.substitutions, filename.string());
|
||||
|
||||
// BBS
|
||||
this->model.plates_custom_gcodes = model.plates_custom_gcodes;
|
||||
this->model.design_info = model.design_info;
|
||||
this->model.model_info = model.model_info;
|
||||
if (load_model && !load_config) {
|
||||
;
|
||||
}
|
||||
else {
|
||||
this->model.plates_custom_gcodes = model.plates_custom_gcodes;
|
||||
this->model.design_info = model.design_info;
|
||||
this->model.model_info = model.model_info;
|
||||
}
|
||||
}
|
||||
|
||||
if (load_config) {
|
||||
|
|
@ -3491,7 +3511,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||
// convert_model_if(model, answer_convert_from_imperial_units == wxID_YES);
|
||||
}
|
||||
|
||||
if (model.looks_like_multipart_object()) {
|
||||
if (!is_project_file && model.looks_like_multipart_object()) {
|
||||
MessageDialog msg_dlg(q, _L(
|
||||
"This file contains several objects positioned at multiple heights.\n"
|
||||
"Instead of considering them as multiple objects, should \n"
|
||||
|
|
@ -3557,9 +3577,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||
q->model().load_from(model);
|
||||
load_auxiliary_files();
|
||||
}
|
||||
// BBS: don't allow negative_z when load model objects
|
||||
// auto loaded_idxs = load_model_objects(model.objects, is_project_file);
|
||||
auto loaded_idxs = load_model_objects(model.objects);
|
||||
auto loaded_idxs = load_model_objects(model.objects, is_project_file);
|
||||
obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end());
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_LOAD_MODEL_OBJECTS \n");
|
||||
|
|
@ -3845,7 +3863,7 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs& mode
|
|||
void Plater::priv::load_auxiliary_files()
|
||||
{
|
||||
std::string auxiliary_path = encode_path(q->model().get_auxiliary_file_temp_path().c_str());
|
||||
wxGetApp().mainframe->m_auxiliary->Reload(auxiliary_path);
|
||||
//wxGetApp().mainframe->m_project->Reload(auxiliary_path);
|
||||
}
|
||||
|
||||
fs::path Plater::priv::get_export_file_path(GUI::FileType file_type)
|
||||
|
|
@ -4059,13 +4077,31 @@ void Plater::priv::remove(size_t obj_idx)
|
|||
}
|
||||
|
||||
|
||||
void Plater::priv::delete_object_from_model(size_t obj_idx, bool refresh_immediately)
|
||||
bool Plater::priv::delete_object_from_model(size_t obj_idx, bool refresh_immediately)
|
||||
{
|
||||
// check if object isn't cut
|
||||
// show warning message that "cut consistancy" will not be supported any more
|
||||
ModelObject *obj = model.objects[obj_idx];
|
||||
if (obj->is_cut()) {
|
||||
InfoDialog dialog(q, _L("Delete object which is a part of cut object"),
|
||||
_L("You try to delete an object which is a part of a cut object.\n"
|
||||
"This action will break a cut correspondence.\n"
|
||||
"After that model consistency can't be guaranteed."),
|
||||
false, wxYES | wxCANCEL | wxCANCEL_DEFAULT | wxICON_WARNING);
|
||||
dialog.SetButtonLabel(wxID_YES, _L("Delete"));
|
||||
if (dialog.ShowModal() == wxID_CANCEL)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string snapshot_label = "Delete Object";
|
||||
if (! model.objects[obj_idx]->name.empty())
|
||||
snapshot_label += ": " + model.objects[obj_idx]->name;
|
||||
if (!obj->name.empty())
|
||||
snapshot_label += ": " + obj->name;
|
||||
Plater::TakeSnapshot snapshot(q, snapshot_label);
|
||||
m_ui_jobs.cancel_all();
|
||||
|
||||
if (obj->is_cut())
|
||||
sidebar->obj_list()->invalidate_cut_info_for_object(obj_idx);
|
||||
|
||||
model.delete_object(obj_idx);
|
||||
//BBS: notify partplate the instance removed
|
||||
partplate_list.notify_instance_removed(obj_idx, -1);
|
||||
|
|
@ -4075,6 +4111,8 @@ void Plater::priv::delete_object_from_model(size_t obj_idx, bool refresh_immedia
|
|||
update();
|
||||
object_list_changed();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Plater::priv::delete_all_objects_from_model()
|
||||
|
|
@ -6469,9 +6507,10 @@ void Plater::priv::on_3dcanvas_mouse_dragging_finished(SimpleEvent&)
|
|||
}
|
||||
|
||||
//BBS: add plate id for thumbnail generate param
|
||||
void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type)
|
||||
void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
|
||||
Camera::EType camera_type, bool use_top_view, bool for_picking)
|
||||
{
|
||||
view3D->get_canvas3d()->render_thumbnail(data, w, h, thumbnail_params, camera_type);
|
||||
view3D->get_canvas3d()->render_thumbnail(data, w, h, thumbnail_params, camera_type, use_top_view, for_picking);
|
||||
}
|
||||
|
||||
//BBS: add plate id for thumbnail generate param
|
||||
|
|
@ -6863,22 +6902,29 @@ bool Plater::priv::has_assemble_view() const
|
|||
bool Plater::priv::can_scale_to_print_volume() const
|
||||
{
|
||||
const BuildVolume_Type type = this->bed.build_volume().type();
|
||||
return !view3D->get_canvas3d()->get_selection().is_empty() && (type == BuildVolume_Type::Rectangle || type == BuildVolume_Type::Circle);
|
||||
return !sidebar->obj_list()->has_selected_cut_object()
|
||||
&& !view3D->get_canvas3d()->get_selection().is_empty()
|
||||
&& (type == BuildVolume_Type::Rectangle || type == BuildVolume_Type::Circle);
|
||||
}
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
bool Plater::priv::can_mirror() const
|
||||
{
|
||||
return get_selection().is_from_single_instance();
|
||||
return !sidebar->obj_list()->has_selected_cut_object()
|
||||
&& get_selection().is_from_single_instance();
|
||||
}
|
||||
|
||||
bool Plater::priv::can_replace_with_stl() const
|
||||
{
|
||||
return get_selection().get_volume_idxs().size() == 1;
|
||||
return !sidebar->obj_list()->has_selected_cut_object()
|
||||
&& get_selection().get_volume_idxs().size() == 1;
|
||||
}
|
||||
|
||||
bool Plater::priv::can_reload_from_disk() const
|
||||
{
|
||||
if (sidebar->obj_list()->has_selected_cut_object())
|
||||
return false;
|
||||
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
// collect selected reloadable ModelVolumes
|
||||
std::vector<std::pair<int, int>> selected_volumes = reloadable_volumes(model, get_selection());
|
||||
|
|
@ -7089,7 +7135,8 @@ bool Plater::priv::can_increase_instances() const
|
|||
return false;
|
||||
|
||||
int obj_idx = get_selected_object_idx();
|
||||
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
|
||||
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size())
|
||||
&& !sidebar->obj_list()->has_selected_cut_object();
|
||||
}
|
||||
|
||||
bool Plater::priv::can_decrease_instances() const
|
||||
|
|
@ -7099,7 +7146,8 @@ bool Plater::priv::can_decrease_instances() const
|
|||
return false;
|
||||
|
||||
int obj_idx = get_selected_object_idx();
|
||||
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
|
||||
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1)
|
||||
&& !sidebar->obj_list()->has_selected_cut_object();
|
||||
}
|
||||
|
||||
bool Plater::priv::can_split_to_objects() const
|
||||
|
|
@ -7566,7 +7614,7 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_
|
|||
(yes_or_no ? _L("You can keep the modified presets to the new project or discard them") :
|
||||
_L("You can keep the modifield presets to the new project, discard or save changes as new presets."));
|
||||
using ab = UnsavedChangesDialog::ActionButtons;
|
||||
int act_buttons = ab::KEEP;
|
||||
int act_buttons = ab::KEEP | ab::REMEMBER_CHOISE;
|
||||
if (!yes_or_no)
|
||||
act_buttons |= ab::SAVE;
|
||||
return wxGetApp().check_and_keep_current_preset_changes(_L("Creating a new project"), header, act_buttons, &transfer_preset_changes);
|
||||
|
|
@ -7701,6 +7749,8 @@ void Plater::load_project(wxString const& filename2,
|
|||
// if res is empty no data has been loaded
|
||||
if (!res.empty() && (load_restore || !(strategy & LoadStrategy::Silence))) {
|
||||
p->set_project_filename(load_restore ? originfile : filename);
|
||||
if (load_restore && originfile.IsEmpty())
|
||||
p->set_project_name(_L("Untitled"));
|
||||
} else {
|
||||
if (using_exported_file())
|
||||
p->set_project_filename(filename);
|
||||
|
|
@ -7772,15 +7822,13 @@ int Plater::save_project(bool saveAs)
|
|||
//BBS import model by model id
|
||||
void Plater::import_model_id(const std::string& download_info)
|
||||
{
|
||||
std::string download_url = wxGetApp().get_download_model_url();
|
||||
std::string filename = wxGetApp().get_download_model_name();
|
||||
std::string download_url;
|
||||
std::string filename;
|
||||
|
||||
/* auto selection_data_arr = wxSplit(download_info, '|');
|
||||
|
||||
if (selection_data_arr.size() == 2) {
|
||||
download_url = selection_data_arr[0].ToStdString();
|
||||
filename = selection_data_arr[1].ToStdString();
|
||||
}*/
|
||||
std::string download_origin_url = wxGetApp().url_decode(download_info);
|
||||
fs::path download_path = fs::path(download_origin_url);
|
||||
download_url = download_origin_url;
|
||||
filename = download_path.filename().string();
|
||||
|
||||
|
||||
bool download_ok = false;
|
||||
|
|
@ -7957,9 +8005,10 @@ void Plater::download_project(const wxString& project_id)
|
|||
return;
|
||||
}
|
||||
|
||||
void Plater::request_model_download()
|
||||
void Plater::request_model_download(std::string url)
|
||||
{
|
||||
wxCommandEvent* event = new wxCommandEvent(EVT_IMPORT_MODEL_ID);
|
||||
event->SetString(url);
|
||||
wxQueueEvent(this, event);
|
||||
}
|
||||
|
||||
|
|
@ -9218,14 +9267,21 @@ int GUI::Plater::close_with_confirm(std::function<bool(bool)> second_check)
|
|||
return wxID_NO;
|
||||
}
|
||||
|
||||
auto result = MessageDialog(static_cast<wxWindow*>(this), _L("The current project has unsaved changes, save it before continue?"),
|
||||
wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Save"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal();
|
||||
MessageDialog dlg(static_cast<wxWindow*>(this), _L("The current project has unsaved changes, save it before continue?"),
|
||||
wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Save"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE);
|
||||
dlg.show_dsa_button(_L("Remember my choice."));
|
||||
auto choise = wxGetApp().app_config->get("save_project_choise");
|
||||
auto result = choise.empty() ? dlg.ShowModal() : choise == "yes" ? wxID_YES : wxID_NO;
|
||||
if (result == wxID_CANCEL)
|
||||
return result;
|
||||
else if (result == wxID_YES) {
|
||||
result = save_project();
|
||||
if (result == wxID_CANCEL)
|
||||
return result;
|
||||
else {
|
||||
if (dlg.get_checkbox_state())
|
||||
wxGetApp().app_config->set("save_project_choise", result == wxID_YES ? "yes" : "no");
|
||||
if (result == wxID_YES) {
|
||||
result = save_project();
|
||||
if (result == wxID_CANCEL)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (second_check && !second_check(result == wxID_YES)) return wxID_CANCEL;
|
||||
|
|
@ -9247,7 +9303,7 @@ void Plater::trigger_restore_project(int skip_confirm)
|
|||
}
|
||||
|
||||
//BBS
|
||||
void Plater::delete_object_from_model(size_t obj_idx, bool refresh_immediately) { p->delete_object_from_model(obj_idx, refresh_immediately); }
|
||||
bool Plater::delete_object_from_model(size_t obj_idx, bool refresh_immediately) { return p->delete_object_from_model(obj_idx, refresh_immediately); }
|
||||
|
||||
//BBS: delete all from model
|
||||
void Plater::delete_all_objects_from_model()
|
||||
|
|
@ -9459,8 +9515,6 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, std::array<Vec3d, 4> plane
|
|||
if (! attributes.has(ModelObjectCutAttribute::KeepUpper) && ! attributes.has(ModelObjectCutAttribute::KeepLower))
|
||||
return;
|
||||
|
||||
Plater::TakeSnapshot snapshot(this, "Cut by Plane");
|
||||
|
||||
wxBusyCursor wait;
|
||||
// BBS: replace z with plane_points
|
||||
const auto new_objects = object->cut(instance_idx, plane_points, attributes);
|
||||
|
|
@ -9468,6 +9522,14 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, std::array<Vec3d, 4> plane
|
|||
remove(obj_idx);
|
||||
p->load_model_objects(new_objects);
|
||||
|
||||
// now process all updates of the 3d scene
|
||||
update();
|
||||
|
||||
// Update InfoItems in ObjectList after update() to use of a correct value of the GLCanvas3D::is_sinking(),
|
||||
// which is updated after a view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH) call
|
||||
for (size_t idx = 0; idx < p->model.objects.size(); idx++)
|
||||
wxGetApp().obj_list()->update_info_items(idx);
|
||||
|
||||
Selection& selection = p->get_selection();
|
||||
size_t last_id = p->model.objects.size() - 1;
|
||||
for (size_t i = 0; i < new_objects.size(); ++i)
|
||||
|
|
@ -9903,6 +9965,7 @@ void Plater::export_stl(bool extended, bool selection_only)
|
|||
// BBS: backup
|
||||
int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy strategy, int export_plate_idx, Export3mfProgressFn proFn)
|
||||
{
|
||||
int ret = 0;
|
||||
//if (p->model.objects.empty()) {
|
||||
// MessageDialog dialog(nullptr, _L("No objects to export."), _L("Save project"), wxYES);
|
||||
// if (dialog.ShowModal() == wxYES)
|
||||
|
|
@ -9928,6 +9991,8 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
|||
//BBS: add plate logic for thumbnail generate
|
||||
std::vector<ThumbnailData*> thumbnails;
|
||||
std::vector<ThumbnailData*> calibration_thumbnails;
|
||||
std::vector<ThumbnailData*> top_thumbnails;
|
||||
std::vector<ThumbnailData*> picking_thumbnails;
|
||||
std::vector<PlateBBoxData*> plate_bboxes;
|
||||
// BBS: backup
|
||||
if (!(strategy & SaveStrategy::Backup)) {
|
||||
|
|
@ -9940,22 +10005,50 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
|||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": re-generate thumbnail for plate %1%") % i;
|
||||
const ThumbnailsParams thumbnail_params = { {}, false, true, true, true, i };
|
||||
p->generate_thumbnail(p->partplate_list.get_plate(i)->thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, thumbnail_params, Camera::EType::Ortho);
|
||||
p->generate_thumbnail(p->partplate_list.get_plate(i)->thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second,
|
||||
thumbnail_params, Camera::EType::Ortho);
|
||||
}
|
||||
thumbnails.push_back(thumbnail_data);
|
||||
|
||||
ThumbnailData* calibration_data = &p->partplate_list.get_plate(i)->cali_thumbnail_data;
|
||||
calibration_thumbnails.push_back(calibration_data);
|
||||
//ThumbnailData* calibration_data = &p->partplate_list.get_plate(i)->cali_thumbnail_data;
|
||||
//calibration_thumbnails.push_back(calibration_data);
|
||||
PlateBBoxData* plate_bbox_data = &p->partplate_list.get_plate(i)->cali_bboxes_data;
|
||||
plate_bboxes.push_back(plate_bbox_data);
|
||||
|
||||
//generate top and picking thumbnails
|
||||
ThumbnailData* top_thumbnail = &p->partplate_list.get_plate(i)->top_thumbnail_data;
|
||||
if (top_thumbnail->is_valid() && using_exported_file()) {
|
||||
//no need to generate thumbnail
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": non need to re-generate top_thumbnail for gcode/exported mode of plate %1%")%i;
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": re-generate top_thumbnail for plate %1%") % i;
|
||||
const ThumbnailsParams thumbnail_params = { {}, false, true, false, true, i };
|
||||
p->generate_thumbnail(p->partplate_list.get_plate(i)->top_thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second,
|
||||
thumbnail_params, Camera::EType::Ortho, true, false);
|
||||
}
|
||||
top_thumbnails.push_back(top_thumbnail);
|
||||
|
||||
ThumbnailData* picking_thumbnail = &p->partplate_list.get_plate(i)->pick_thumbnail_data;
|
||||
if (picking_thumbnail->is_valid() && using_exported_file()) {
|
||||
//no need to generate thumbnail
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": non need to re-generate pick_thumbnail for gcode/exported mode of plate %1%")%i;
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": re-generate pick_thumbnail for plate %1%") % i;
|
||||
const ThumbnailsParams thumbnail_params = { {}, false, true, false, true, i };
|
||||
p->generate_thumbnail(p->partplate_list.get_plate(i)->pick_thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second,
|
||||
thumbnail_params, Camera::EType::Ortho, true, true);
|
||||
}
|
||||
picking_thumbnails.push_back(picking_thumbnail);
|
||||
}
|
||||
|
||||
if (p->partplate_list.get_curr_plate()->is_slice_result_valid()) {
|
||||
//BBS generate BBS calibration thumbnails
|
||||
int index = p->partplate_list.get_curr_plate_index();
|
||||
ThumbnailData* calibration_data = calibration_thumbnails[index];
|
||||
const ThumbnailsParams calibration_params = { {}, false, true, true, true, p->partplate_list.get_curr_plate_index() };
|
||||
p->generate_calibration_thumbnail(*calibration_data, PartPlate::cali_thumbnail_width, PartPlate::cali_thumbnail_height, calibration_params);
|
||||
//ThumbnailData* calibration_data = calibration_thumbnails[index];
|
||||
//const ThumbnailsParams calibration_params = { {}, false, true, true, true, p->partplate_list.get_curr_plate_index() };
|
||||
//p->generate_calibration_thumbnail(*calibration_data, PartPlate::cali_thumbnail_width, PartPlate::cali_thumbnail_height, calibration_params);
|
||||
if (using_exported_file()) {
|
||||
//do nothing
|
||||
}
|
||||
|
|
@ -9980,6 +10073,8 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
|||
store_params.project_presets = project_presets;
|
||||
store_params.config = export_config ? &cfg : nullptr;
|
||||
store_params.thumbnail_data = thumbnails;
|
||||
store_params.top_thumbnail_data = top_thumbnails;
|
||||
store_params.pick_thumbnail_data = picking_thumbnails;
|
||||
store_params.calibration_thumbnail_data = calibration_thumbnails;
|
||||
store_params.proFn = proFn;
|
||||
store_params.id_bboxes = plate_bboxes;//BBS
|
||||
|
|
@ -10041,7 +10136,7 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
|||
}
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (project_presets.size() > 0)
|
||||
|
|
@ -10060,8 +10155,20 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
|||
//release the data here, as it will always be generated when export
|
||||
calibration_thumbnails[i]->reset();
|
||||
}
|
||||
for (unsigned int i = 0; i < top_thumbnails.size(); i++)
|
||||
{
|
||||
//release the data here, as it will always be generated when export
|
||||
top_thumbnails[i]->reset();
|
||||
}
|
||||
top_thumbnails.clear();
|
||||
for (unsigned int i = 0; i < picking_thumbnails.size(); i++)
|
||||
{
|
||||
//release the data here, as it will always be generated when export
|
||||
picking_thumbnails[i]->reset();;
|
||||
}
|
||||
picking_thumbnails.clear();
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Plater::publish_project()
|
||||
|
|
@ -10330,9 +10437,7 @@ int Plater::send_gcode(int plate_idx, Export3mfProgressFn proFn)
|
|||
if (plate_idx == PLATE_CURRENT_IDX) {
|
||||
p->m_print_job_data.plate_idx = get_partplate_list().get_curr_plate_index();
|
||||
}
|
||||
else if (plate_idx == PLATE_ALL_IDX) {
|
||||
p->m_print_job_data.plate_idx = get_partplate_list().get_curr_plate_index();
|
||||
} else {
|
||||
else {
|
||||
p->m_print_job_data.plate_idx = plate_idx;
|
||||
}
|
||||
|
||||
|
|
@ -10564,6 +10669,7 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
|
|||
|
||||
if (update_filament_colors_in_full_config()) {
|
||||
p->sidebar->obj_list()->update_filament_colors();
|
||||
dynamic_filament_list.update();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -11084,6 +11190,7 @@ void Plater::sys_color_changed()
|
|||
p->preview->sys_color_changed();
|
||||
p->sidebar->sys_color_changed();
|
||||
p->menus.sys_color_changed();
|
||||
if (p->m_select_machine_dlg) p->m_select_machine_dlg->sys_color_changed();
|
||||
|
||||
Layout();
|
||||
GetParent()->Layout();
|
||||
|
|
@ -11484,8 +11591,10 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click)
|
|||
ret = select_plate(plate_index);
|
||||
if (!ret)
|
||||
{
|
||||
set_prepare_state(Job::PREPARE_STATE_MENU);
|
||||
arrange();
|
||||
if (last_arrange_job_is_finished()) {
|
||||
set_prepare_state(Job::PREPARE_STATE_MENU);
|
||||
arrange();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -11538,6 +11647,7 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click)
|
|||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("select print sequence %1% for plate %2% at plate side")%ps_sel %plate_index;
|
||||
auto plate_config = *(curr_plate->config());
|
||||
wxGetApp().plater()->config_change_notification(plate_config, std::string("print_sequence"));
|
||||
update();
|
||||
});
|
||||
dlg.ShowModal();
|
||||
curr_plate->set_plate_name(dlg.get_plate_name().ToStdString());
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ namespace GUI {
|
|||
class MainFrame;
|
||||
class ConfigOptionsGroup;
|
||||
class ObjectSettings;
|
||||
class ObjectLayers;
|
||||
class ObjectList;
|
||||
class GLCanvas3D;
|
||||
class Mouse3DController;
|
||||
|
|
@ -131,6 +132,7 @@ public:
|
|||
|
||||
ObjectList* obj_list();
|
||||
ObjectSettings* obj_settings();
|
||||
ObjectLayers* obj_layers();
|
||||
wxPanel* scrolled_panel();
|
||||
wxPanel* print_panel();
|
||||
wxPanel* filament_panel();
|
||||
|
|
@ -214,7 +216,7 @@ public:
|
|||
//BBS download project by project id
|
||||
void import_model_id(const std::string& download_info);
|
||||
void download_project(const wxString& project_id);
|
||||
void request_model_download();
|
||||
void request_model_download(std::string url);
|
||||
void request_download_project(std::string project_id);
|
||||
// BBS: check snapshot
|
||||
bool up_to_date(bool saved, bool backup);
|
||||
|
|
@ -305,7 +307,7 @@ public:
|
|||
int close_with_confirm(std::function<bool(bool yes_or_no)> second_check = nullptr); // BBS close project
|
||||
//BBS: trigger a restore project event
|
||||
void trigger_restore_project(int skip_confirm = 0);
|
||||
void delete_object_from_model(size_t obj_idx, bool refresh_immediately = true); // BBS support refresh immediately
|
||||
bool delete_object_from_model(size_t obj_idx, bool refresh_immediately = true); // BBS support refresh immediately
|
||||
void delete_all_objects_from_model(); //BBS delete all objects from model
|
||||
void set_selected_visible(bool visible);
|
||||
void remove_selected();
|
||||
|
|
@ -690,6 +692,13 @@ public:
|
|||
|
||||
std::string get_preview_only_filename() { return m_preview_only_filename; };
|
||||
|
||||
bool last_arrange_job_is_finished()
|
||||
{
|
||||
bool prevRunning = false;
|
||||
return m_arrange_running.compare_exchange_strong(prevRunning, true);
|
||||
};
|
||||
std::atomic<bool> m_arrange_running{false};
|
||||
|
||||
private:
|
||||
struct priv;
|
||||
std::unique_ptr<priv> p;
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@ wxBoxSizer *PreferencesDialog::create_item_language_combobox(
|
|||
else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_JAPANESE)) {
|
||||
language_name = wxString::FromUTF8("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E");
|
||||
}
|
||||
else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_ITALIAN)) {
|
||||
language_name = wxString::FromUTF8("\x69\x74\x61\x6c\x69\x61\x6e\x6f");
|
||||
}
|
||||
|
||||
if (app_config->get(param) == vlist[i]->CanonicalName) {
|
||||
m_current_language_selected = i;
|
||||
|
|
@ -381,10 +384,55 @@ wxBoxSizer *PreferencesDialog::create_item_multiple_combobox(
|
|||
return m_sizer_tcombox;
|
||||
}
|
||||
|
||||
wxBoxSizer *PreferencesDialog::create_item_input(wxString title, wxString title2, wxWindow *parent, wxString tooltip, std::string param, std::function<void(wxString)> onchange)
|
||||
{
|
||||
wxBoxSizer *sizer_input = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto input_title = new wxStaticText(parent, wxID_ANY, title);
|
||||
input_title->SetForegroundColour(DESIGN_GRAY900_COLOR);
|
||||
input_title->SetFont(::Label::Body_13);
|
||||
input_title->SetToolTip(tooltip);
|
||||
input_title->Wrap(-1);
|
||||
|
||||
auto input = new ::TextInput(parent, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, DESIGN_INPUT_SIZE, wxTE_PROCESS_ENTER);
|
||||
StateColor input_bg(std::pair<wxColour, int>(wxColour("#F0F0F1"), StateColor::Disabled), std::pair<wxColour, int>(*wxWHITE, StateColor::Enabled));
|
||||
input->SetBackgroundColor(input_bg);
|
||||
input->GetTextCtrl()->SetValue(app_config->get(param));
|
||||
|
||||
auto second_title = new wxStaticText(parent, wxID_ANY, title2, wxDefaultPosition, DESIGN_TITLE_SIZE, 0);
|
||||
second_title->SetForegroundColour(DESIGN_GRAY900_COLOR);
|
||||
second_title->SetFont(::Label::Body_13);
|
||||
second_title->SetToolTip(tooltip);
|
||||
second_title->Wrap(-1);
|
||||
|
||||
sizer_input->Add(0, 0, 0, wxEXPAND | wxLEFT, 23);
|
||||
sizer_input->Add(input_title, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3);
|
||||
sizer_input->Add(input, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
sizer_input->Add(0, 0, 0, wxEXPAND | wxLEFT, 3);
|
||||
sizer_input->Add(second_title, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3);
|
||||
|
||||
input->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this, param, input, onchange](wxCommandEvent &e) {
|
||||
auto value = input->GetTextCtrl()->GetValue();
|
||||
app_config->set(param, std::string(value.mb_str()));
|
||||
app_config->save();
|
||||
onchange(value);
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
input->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this, param, input, onchange](wxFocusEvent &e) {
|
||||
auto value = input->GetTextCtrl()->GetValue();
|
||||
app_config->set(param, std::string(value.mb_str()));
|
||||
app_config->save();
|
||||
onchange(value);
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
return sizer_input;
|
||||
}
|
||||
|
||||
wxBoxSizer *PreferencesDialog::create_item_backup_input(wxString title, wxWindow *parent, wxString tooltip, std::string param)
|
||||
{
|
||||
wxBoxSizer *m_sizer_input = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto input_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, DESIGN_TITLE_SIZE, 0);
|
||||
auto input_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, 0);
|
||||
input_title->SetForegroundColour(DESIGN_GRAY900_COLOR);
|
||||
input_title->SetFont(::Label::Body_13);
|
||||
input_title->SetToolTip(tooltip);
|
||||
|
|
@ -403,10 +451,10 @@ wxBoxSizer *PreferencesDialog::create_item_backup_input(wxString title, wxWindow
|
|||
second_title->Wrap(-1);
|
||||
|
||||
m_sizer_input->Add(0, 0, 0, wxEXPAND | wxLEFT, 23);
|
||||
m_sizer_input->Add(input_title, 0, wxALIGN_CENTER | wxALL, 3);
|
||||
m_sizer_input->Add(input, 0, wxALIGN_CENTER, 0);
|
||||
m_sizer_input->Add(input_title, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3);
|
||||
m_sizer_input->Add(input, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
m_sizer_input->Add(0, 0, 0, wxEXPAND | wxLEFT, 3);
|
||||
m_sizer_input->Add(second_title, 0, wxALIGN_CENTER| wxALL, 3);
|
||||
m_sizer_input->Add(second_title, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3);
|
||||
|
||||
|
||||
input->GetTextCtrl()->Bind(wxEVT_COMMAND_TEXT_UPDATED, [this, param, input](wxCommandEvent &e) {
|
||||
|
|
@ -418,6 +466,9 @@ wxBoxSizer *PreferencesDialog::create_item_backup_input(wxString title, wxWindow
|
|||
m_backup_interval_time = input->GetTextCtrl()->GetValue();
|
||||
app_config->set("backup_interval", std::string(m_backup_interval_time.mb_str()));
|
||||
app_config->save();
|
||||
long backup_interval = 0;
|
||||
m_backup_interval_time.ToLong(&backup_interval);
|
||||
Slic3r::set_backup_interval(backup_interval);
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
|
|
@ -425,6 +476,9 @@ wxBoxSizer *PreferencesDialog::create_item_backup_input(wxString title, wxWindow
|
|||
m_backup_interval_time = input->GetTextCtrl()->GetValue();
|
||||
app_config->set("backup_interval", std::string(m_backup_interval_time.mb_str()));
|
||||
app_config->save();
|
||||
long backup_interval = 0;
|
||||
m_backup_interval_time.ToLong(&backup_interval);
|
||||
Slic3r::set_backup_interval(backup_interval);
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
|
|
@ -543,7 +597,7 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa
|
|||
checkbox_title->SetFont(::Label::Body_13);
|
||||
|
||||
auto size = checkbox_title->GetTextExtent(title);
|
||||
checkbox_title->SetMinSize(wxSize(size.x + FromDIP(40), -1));
|
||||
checkbox_title->SetMinSize(wxSize(size.x + FromDIP(4), -1));
|
||||
checkbox_title->Wrap(-1);
|
||||
m_sizer_checkbox->Add(checkbox_title, 0, wxALIGN_CENTER | wxALL, 3);
|
||||
|
||||
|
|
@ -556,6 +610,9 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa
|
|||
// backup
|
||||
if (param == "backup_switch") {
|
||||
bool pbool = app_config->get("backup_switch") == "true" ? true : false;
|
||||
std::string backup_interval = "10";
|
||||
app_config->get("backup_interval", backup_interval);
|
||||
Slic3r::set_backup_interval(pbool ? boost::lexical_cast<long>(backup_interval) : 0);
|
||||
if (m_backup_interval_textinput != nullptr) { m_backup_interval_textinput->Enable(pbool); }
|
||||
}
|
||||
|
||||
|
|
@ -615,6 +672,41 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa
|
|||
return m_sizer_checkbox;
|
||||
}
|
||||
|
||||
wxBoxSizer *PreferencesDialog::create_item_button(wxString title, wxString title2, wxWindow *parent, wxString tooltip, std::function<void()> onclick)
|
||||
{
|
||||
wxBoxSizer *m_sizer_checkbox = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23);
|
||||
auto m_staticTextPath = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
// m_staticTextPath->SetMaxSize(wxSize(FromDIP(440), -1));
|
||||
m_staticTextPath->SetForegroundColour(DESIGN_GRAY900_COLOR);
|
||||
m_staticTextPath->SetFont(::Label::Body_13);
|
||||
m_staticTextPath->Wrap(-1);
|
||||
|
||||
auto m_button_download = new Button(parent, title2);
|
||||
|
||||
StateColor abort_bg(std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Disabled), std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Enabled),
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal));
|
||||
m_button_download->SetBackgroundColor(abort_bg);
|
||||
StateColor abort_bd(std::pair<wxColour, int>(wxColour(144, 144, 144), StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
|
||||
m_button_download->SetBorderColor(abort_bd);
|
||||
StateColor abort_text(std::pair<wxColour, int>(wxColour(144, 144, 144), StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
|
||||
m_button_download->SetTextColor(abort_text);
|
||||
m_button_download->SetFont(Label::Body_10);
|
||||
m_button_download->SetMinSize(wxSize(FromDIP(58), FromDIP(22)));
|
||||
m_button_download->SetSize(wxSize(FromDIP(58), FromDIP(22)));
|
||||
m_button_download->SetCornerRadius(FromDIP(12));
|
||||
m_button_download->SetToolTip(tooltip);
|
||||
|
||||
m_button_download->Bind(wxEVT_BUTTON, [this, onclick](auto &e) { onclick(); });
|
||||
|
||||
m_sizer_checkbox->Add(m_staticTextPath, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
|
||||
m_sizer_checkbox->Add(m_button_download, 0, wxALL, FromDIP(5));
|
||||
|
||||
return m_sizer_checkbox;
|
||||
}
|
||||
|
||||
wxWindow* PreferencesDialog::create_item_downloads(wxWindow* parent, int padding_left, std::string param)
|
||||
{
|
||||
wxString download_path = wxString::FromUTF8(app_config->get("download_path"));
|
||||
|
|
@ -801,7 +893,8 @@ wxWindow* PreferencesDialog::create_general_page()
|
|||
wxLANGUAGE_SWEDISH,
|
||||
wxLANGUAGE_DUTCH,
|
||||
wxLANGUAGE_HUNGARIAN,
|
||||
wxLANGUAGE_JAPANESE
|
||||
wxLANGUAGE_JAPANESE,
|
||||
wxLANGUAGE_ITALIAN
|
||||
};
|
||||
|
||||
auto translations = wxTranslations::Get()->GetAvailableTranslations(SLIC3R_APP_KEY);
|
||||
|
|
@ -826,14 +919,20 @@ wxWindow* PreferencesDialog::create_general_page()
|
|||
std::vector<wxString> Regions = {_L("Asia-Pacific"), _L("China"), _L("Europe"), _L("North America"), _L("Others")};
|
||||
auto item_region= create_item_region_combobox(_L("Login Region"), page, _L("Login Region"), Regions);
|
||||
|
||||
std::vector<wxString> Units = {_L("Metric"), _L("Imperial")};
|
||||
std::vector<wxString> Units = {_L("Metric") + " (mm, g)", _L("Imperial") + " (in, oz)"};
|
||||
auto item_currency = create_item_combobox(_L("Units"), page, _L("Units"), "use_inches", Units);
|
||||
|
||||
auto item_mouse_zoom_settings = create_item_checkbox(_L("Zoom to mouse position"), page, _L("Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center."), 50, "zoom_to_mouse");
|
||||
|
||||
auto item_hints = create_item_checkbox(_L("Show \"Tip of the day\" notification after start"), page, _L("If enabled, useful hints are displayed at startup."), 50, "show_hints");
|
||||
auto item_gcode_window = create_item_checkbox(_L("Show g-code window"), page, _L("If enabled, g-code window will be displayed."), 50, "show_gcode_window");
|
||||
|
||||
auto title_sync_settings = create_item_title(_L("User sync"), page, _L("User sync"));
|
||||
auto title_presets = create_item_title(_L("Presets"), page, _L("Presets"));
|
||||
auto item_user_sync = create_item_checkbox(_L("Auto sync user presets(Printer/Filament/Process)"), page, _L("User Sync"), 50, "sync_user_preset");
|
||||
auto item_system_sync = create_item_checkbox(_L("Update built-in Presets automatically."), page, _L("System Sync"), 50, "sync_system_preset");
|
||||
auto item_save_presets = create_item_button(_L("Clear my choice on the unsaved presets."), _L("Clear"), page, _L("Clear my choice on the unsaved presets."), []() {
|
||||
wxGetApp().app_config->set("save_preset_choise", "");
|
||||
});
|
||||
|
||||
#ifdef _WIN32
|
||||
auto title_associate_file = create_item_title(_L("Associate files to OrcaSlicer"), page, _L("Associate files to OrcaSlicer"));
|
||||
|
|
@ -847,11 +946,18 @@ wxWindow* PreferencesDialog::create_general_page()
|
|||
_L("If enabled, sets OrcaSlicer as default application to open .step files"), 50, "associate_step");
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
auto title_backup = create_item_title(_L("Backup"), page, _L("Backup"));
|
||||
//auto item_backup = create_item_switch(_L("Backup switch"), page, _L("Backup switch"), "units");
|
||||
auto item_backup = create_item_checkbox(_L("Auto-Backup"), page,_L("Auto-Backup"), 50, "backup_switch");
|
||||
auto item_backup_interval = create_item_backup_input(_L("Backup interval"), page, _L("Backup interval"), "backup_interval");
|
||||
auto title_project = create_item_title(_L("Project"), page, "");
|
||||
auto item_max_recent_count = create_item_input(_L("Maximum recent projects"), "", page, _L("Maximum count of recent projects"), "max_recent_count", [](wxString value) {
|
||||
long max = 0;
|
||||
if (value.ToLong(&max))
|
||||
wxGetApp().mainframe->set_max_recent_count(max);
|
||||
});
|
||||
auto item_save_choise = create_item_button(_L("Clear my choice on the unsaved projects."), _L("Clear"), page, _L("Clear my choice on the unsaved projects."), []() {
|
||||
wxGetApp().app_config->set("save_project_choise", "");
|
||||
});
|
||||
// auto item_backup = create_item_switch(_L("Backup switch"), page, _L("Backup switch"), "units");
|
||||
auto item_backup = create_item_checkbox(_L("Auto-Backup"), page,_L("Backup your project periodically for restoring from the occasional crash."), 50, "backup_switch");
|
||||
auto item_backup_interval = create_item_backup_input(_L("every"), page, _L("The peroid of backup in seconds."), "backup_interval");
|
||||
|
||||
//downloads
|
||||
auto title_downloads = create_item_title(_L("Downloads"), page, _L("Downloads"));
|
||||
|
|
@ -868,19 +974,24 @@ wxWindow* PreferencesDialog::create_general_page()
|
|||
sizer_page->Add(item_language, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_region, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_currency, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_mouse_zoom_settings, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_hints, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_gcode_window, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(title_sync_settings, 0, wxTOP | wxEXPAND, FromDIP(20));
|
||||
sizer_page->Add(title_presets, 0, wxTOP | wxEXPAND, FromDIP(20));
|
||||
sizer_page->Add(item_user_sync, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_system_sync, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_save_presets, 0, wxTOP, FromDIP(3));
|
||||
#ifdef _WIN32
|
||||
sizer_page->Add(title_associate_file, 0, wxTOP| wxEXPAND, FromDIP(20));
|
||||
sizer_page->Add(item_associate_3mf, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_associate_stl, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_associate_step, 0, wxTOP, FromDIP(3));
|
||||
#endif // _WIN32
|
||||
sizer_page->Add(title_backup, 0, wxTOP| wxEXPAND, FromDIP(20));
|
||||
sizer_page->Add(title_project, 0, wxTOP| wxEXPAND, FromDIP(20));
|
||||
sizer_page->Add(item_max_recent_count, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_save_choise, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_backup, 0, wxTOP,FromDIP(3));
|
||||
sizer_page->Add(item_backup_interval, 0, wxTOP,FromDIP(3));
|
||||
item_backup->Add(item_backup_interval, 0, wxLEFT, 0);
|
||||
|
||||
sizer_page->Add(title_downloads, 0, wxTOP| wxEXPAND, FromDIP(20));
|
||||
sizer_page->Add(item_downloads, 0, wxEXPAND, FromDIP(3));
|
||||
|
|
|
|||
|
|
@ -110,8 +110,9 @@ public:
|
|||
wxBoxSizer *create_item_checkbox(wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string param);
|
||||
wxBoxSizer *create_item_darkmode_checkbox(wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string param);
|
||||
void set_dark_mode();
|
||||
wxBoxSizer *create_item_button(wxString title, wxString title2, wxWindow *parent, wxString tooltip, std::function<void()> onclick);
|
||||
wxWindow* create_item_downloads(wxWindow* parent, int padding_left, std::string param);
|
||||
wxBoxSizer* create_item_backup_checkbox(wxString title, wxWindow* parent, wxString tooltip, int padding_left, std::string param);
|
||||
wxBoxSizer *create_item_input(wxString title, wxString title2, wxWindow *parent, wxString tooltip, std::string param, std::function<void(wxString)> onchange = {});
|
||||
wxBoxSizer *create_item_backup_input(wxString title, wxWindow *parent, wxString tooltip, std::string param);
|
||||
wxBoxSizer *create_item_multiple_combobox(
|
||||
wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string parama, std::vector<wxString> vlista, std::vector<wxString> vlistb);
|
||||
|
|
|
|||
|
|
@ -691,7 +691,7 @@ PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset
|
|||
m_clrData.SetChooseAlpha(false);
|
||||
|
||||
wxColourDialog dialog(this, &m_clrData);
|
||||
dialog.SetTitle("Please choose the filament colour");
|
||||
dialog.SetTitle(_L("Please choose the filament colour"));
|
||||
if ( dialog.ShowModal() == wxID_OK )
|
||||
{
|
||||
m_clrData = dialog.GetColourData();
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ void PrinterFileSystem::SetGroupMode(GroupMode mode)
|
|||
return;
|
||||
this->m_group_mode = mode;
|
||||
m_lock_start = m_lock_end = 0;
|
||||
UpdateGroupSelect();
|
||||
SendChangedEvent(EVT_MODE_CHANGED);
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +132,7 @@ void PrinterFileSystem::ListAllFiles()
|
|||
}
|
||||
}
|
||||
BuildGroups();
|
||||
UpdateGroupSelect();
|
||||
m_status = Status::ListReady;
|
||||
SendChangedEvent(EVT_STATUS_CHANGED, m_status);
|
||||
SendChangedEvent(EVT_FILE_CHANGED);
|
||||
|
|
@ -253,7 +255,28 @@ size_t PrinterFileSystem::GetIndexAtTime(boost::uint32_t time)
|
|||
|
||||
void PrinterFileSystem::ToggleSelect(size_t index)
|
||||
{
|
||||
if (index < m_file_list.size()) {
|
||||
if (m_group_mode != G_NONE) {
|
||||
size_t beg = m_group_mode == G_YEAR ? m_group_month[m_group_year[index]] : m_group_month[index];
|
||||
size_t end_month = m_group_mode == G_YEAR ? ((index + 1) < m_group_year.size() ? m_group_year[index + 1] : m_group_month.size()) : index + 1;
|
||||
size_t end = end_month < m_group_month.size() ? m_group_month[end_month] : m_file_list.size();
|
||||
if ((m_group_flags[index] & FF_SELECT) == 0) {
|
||||
for (int i = beg; i < end; ++i) {
|
||||
if ((m_file_list[i].flags & FF_SELECT) == 0) {
|
||||
m_file_list[i].flags |= FF_SELECT;
|
||||
++m_select_count;
|
||||
}
|
||||
}
|
||||
m_group_flags[index] |= FF_SELECT;
|
||||
} else {
|
||||
for (int i = beg; i < end; ++i) {
|
||||
if (m_file_list[i].flags & FF_SELECT) {
|
||||
m_file_list[i].flags &= ~FF_SELECT;
|
||||
--m_select_count;
|
||||
}
|
||||
}
|
||||
m_group_flags[index] &= ~FF_SELECT;
|
||||
}
|
||||
} else if (index < m_file_list.size()) {
|
||||
m_file_list[index].flags ^= FF_SELECT;
|
||||
if (m_file_list[index].flags & FF_SELECT)
|
||||
++m_select_count;
|
||||
|
|
@ -268,9 +291,11 @@ void PrinterFileSystem::SelectAll(bool select)
|
|||
if (select) {
|
||||
for (auto &f : m_file_list) f.flags |= FF_SELECT;
|
||||
m_select_count = m_file_list.size();
|
||||
for (auto &s : m_group_flags) s |= FF_SELECT;
|
||||
} else {
|
||||
for (auto &f : m_file_list) f.flags &= ~FF_SELECT;
|
||||
m_select_count = 0;
|
||||
for (auto &s : m_group_flags) s &= ~FF_SELECT;
|
||||
}
|
||||
SendChangedEvent(EVT_SELECT_CHANGED, m_select_count);
|
||||
}
|
||||
|
|
@ -289,6 +314,17 @@ PrinterFileSystem::File const &PrinterFileSystem::GetFile(size_t index)
|
|||
{
|
||||
if (m_group_mode == G_NONE)
|
||||
return m_file_list[index];
|
||||
if (m_group_mode == G_YEAR) index = m_group_year[index];
|
||||
return m_file_list[m_group_month[index]];
|
||||
}
|
||||
|
||||
PrinterFileSystem::File const &PrinterFileSystem::GetFile(size_t index, bool &select)
|
||||
{
|
||||
if (m_group_mode == G_NONE) {
|
||||
select = m_file_list[index].IsSelect();
|
||||
return m_file_list[index];
|
||||
}
|
||||
select = m_group_flags[index] & FF_SELECT;
|
||||
if (m_group_mode == G_YEAR)
|
||||
index = m_group_year[index];
|
||||
return m_file_list[m_group_month[index]];
|
||||
|
|
@ -380,6 +416,26 @@ void PrinterFileSystem::BuildGroups()
|
|||
}
|
||||
}
|
||||
|
||||
void PrinterFileSystem::UpdateGroupSelect()
|
||||
{
|
||||
m_group_flags.clear();
|
||||
int beg = 0;
|
||||
if (m_group_mode != G_NONE) {
|
||||
auto group = m_group_mode == G_YEAR ? m_group_year : m_group_month;
|
||||
if (m_group_mode == G_YEAR)
|
||||
for (auto &g : group) g = m_group_month[g];
|
||||
m_group_flags.resize(group.size(), FF_SELECT);
|
||||
for (int i = 0; i < m_file_list.size(); ++i) {
|
||||
if ((m_file_list[i].flags & FF_SELECT) == 0) {
|
||||
auto iter = std::upper_bound(group.begin(), group.end(), i);
|
||||
m_group_flags[iter - group.begin() - 1] &= ~FF_SELECT;
|
||||
if (iter == group.end()) break;
|
||||
i = *iter - 1; // start from next group
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinterFileSystem::DeleteFilesContinue()
|
||||
{
|
||||
std::vector<size_t> indexes;
|
||||
|
|
@ -481,14 +537,12 @@ void PrinterFileSystem::DownloadNextFile()
|
|||
download->index = FindFile(download->index, download->name);
|
||||
if (download->index != size_t(-1)) {
|
||||
int progress = data.size * 100 / data.total;
|
||||
if (result > CONTINUE)
|
||||
progress = -2;
|
||||
auto & file = m_file_list[download->index];
|
||||
if (result == ERROR_CANCEL)
|
||||
file.flags &= ~FF_DOWNLOAD;
|
||||
else if (file.progress != progress) {
|
||||
file.progress = progress;
|
||||
SendChangedEvent(EVT_DOWNLOAD, download->index, file.path, data.size);
|
||||
SendChangedEvent(EVT_DOWNLOAD, download->index, file.path, result);
|
||||
}
|
||||
}
|
||||
if (result != CONTINUE) DownloadNextFile();
|
||||
|
|
@ -586,9 +640,14 @@ void PrinterFileSystem::FileRemoved(size_t index, std::string const &name)
|
|||
size_t index2 = removeFromGroup(m_group_month, index, m_file_list.size());
|
||||
if (index2 < m_group_month.size()) {
|
||||
int index3 = removeFromGroup(m_group_year, index, m_group_month.size());
|
||||
if (index3 < m_group_year.size())
|
||||
if (index3 < m_group_year.size()) {
|
||||
m_group_year.erase(m_group_year.begin() + index3);
|
||||
if (m_group_mode == G_YEAR)
|
||||
m_group_flags.erase(m_group_flags.begin() + index2);
|
||||
}
|
||||
m_group_month.erase(m_group_month.begin() + index2);
|
||||
if (m_group_mode == G_MONTH)
|
||||
m_group_flags.erase(m_group_flags.begin() + index2);
|
||||
}
|
||||
m_file_list.erase(m_file_list.begin() + index);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue