mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 02:41:17 +00:00
fix: merge branch feat/plugin-feature
This commit is contained in:
@@ -495,7 +495,29 @@ void GLVolume::render_with_outline(const GUI::Size& cnv_size)
|
||||
simple_render(shader, model_objects, colors);
|
||||
return;
|
||||
}
|
||||
|
||||
// 0th. render pass, render the model using stencil buffer
|
||||
glsafe(::glEnable(GL_STENCIL_TEST));
|
||||
glsafe(::glStencilMask(0xFF));
|
||||
glsafe(::glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE));
|
||||
glsafe(::glClearStencil(0));
|
||||
glsafe(::glClear(GL_STENCIL_BUFFER_BIT));
|
||||
glsafe(::glStencilFunc(GL_ALWAYS, 0xFF, 0xFF));
|
||||
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
|
||||
model.render(shader);
|
||||
else
|
||||
model.render(this->tverts_range, shader);
|
||||
glsafe(::glStencilFunc(GL_NOTEQUAL, 0xFF, 0xFF));
|
||||
glsafe(::glStencilMask(0x00));
|
||||
shader->set_uniform("is_outline", true);
|
||||
shader->set_uniform("screen_size", Vec2f{cnv_size.get_width(), cnv_size.get_height()});
|
||||
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
|
||||
model.render(shader);
|
||||
else
|
||||
model.render(this->tverts_range, shader);
|
||||
shader->set_uniform("is_outline", false);
|
||||
glsafe(::glStencilMask(0xFF));
|
||||
glsafe(::glDisable(GL_STENCIL_TEST));
|
||||
// render the outline using depth buffer and discard the pixels that are not on the outline
|
||||
// 1st. render pass, render the model into a separate render target that has only depth buffer
|
||||
GLuint depth_fbo = 0;
|
||||
GLuint depth_tex = 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,253 @@
|
||||
#pragma once
|
||||
#include "GUI_ObjectLayers.hpp"
|
||||
#include "slic3r/GUI/Widgets/AMSItem.hpp"
|
||||
#include "slic3r/GUI/Widgets/Label.hpp"
|
||||
#include "slic3r/GUI/Widgets/PopupWindow.hpp"
|
||||
|
||||
#include "slic3r/GUI/wxExtensions.hpp"
|
||||
#include "slic3r/GUI/DeviceCore/DevFilaSystem.h"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
|
||||
|
||||
//Previous defintions
|
||||
class wxGrid;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
|
||||
|
||||
enum class DryCtrState {
|
||||
IDLE,
|
||||
DRY_WHEN_PRINT,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
enum class DryCtrDev {
|
||||
N3S,
|
||||
N3F,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
struct DryingPreset {
|
||||
DryCtrState state;
|
||||
DryCtrDev dev;
|
||||
int dry_temp;
|
||||
int dry_time;
|
||||
};
|
||||
|
||||
class FilamentItemPanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
FilamentItemPanel(wxWindow* parent, const wxString& text, const std::string& icon_name = "",
|
||||
wxWindowID id = wxID_ANY);
|
||||
|
||||
void SetText(const wxString& text);
|
||||
void SetIcon(const std::string& icon_name);
|
||||
void msw_rescale();
|
||||
|
||||
private:
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnSize(wxSizeEvent& event);
|
||||
|
||||
Label* m_text_label;
|
||||
wxStaticBitmap* m_icon_bitmap;
|
||||
int m_target_size;
|
||||
std::string m_icon_name;
|
||||
ScalableBitmap m_icon;
|
||||
};
|
||||
|
||||
class AMSFilamentPanel : public wxPanel
|
||||
{
|
||||
wxBoxSizer* m_filament_sizer;
|
||||
Label* m_ams_name_label;
|
||||
int m_border_radius;
|
||||
wxPanel* m_filament_container{nullptr};
|
||||
std::vector<FilamentItemPanel*> m_filament_items;
|
||||
|
||||
public:
|
||||
AMSFilamentPanel(wxWindow* parent, const wxString& ams_name, wxWindowID id = wxID_ANY);
|
||||
|
||||
void AddFilamentItem(const wxString& text, const std::string& icon_name);
|
||||
void AddFilamentItem(FilamentItemPanel* panel);
|
||||
void SetAmsName(const wxString& ams_name);
|
||||
void Clear();
|
||||
void msw_rescale();
|
||||
private:
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
};
|
||||
|
||||
|
||||
class AMSDryCtrWin : public DPIDialog
|
||||
{
|
||||
public:
|
||||
AMSDryCtrWin(wxWindow *parent);
|
||||
~AMSDryCtrWin();
|
||||
|
||||
void msw_rescale();
|
||||
void update(std::shared_ptr<DevFilaSystem> fila_system, MachineObject* obj);
|
||||
void set_ams_id(const std::string& ams_id);
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
|
||||
private:
|
||||
wxSimplebook* m_main_simplebook{nullptr};
|
||||
wxPanel* m_original_page{nullptr};
|
||||
|
||||
wxWindow* m_amswin{nullptr};
|
||||
wxBoxSizer* m_sizer_ams_items{nullptr};
|
||||
wxScrolledWindow* m_panel_prv_left {nullptr};
|
||||
wxScrolledWindow* m_panel_prv_right{nullptr};
|
||||
wxBoxSizer* m_sizer_prv_left{nullptr};
|
||||
wxBoxSizer* m_sizer_prv_right{nullptr};
|
||||
|
||||
// left panel related members
|
||||
ScalableBitmap m_humidity_image;
|
||||
wxStaticBitmap* m_humidity_img{nullptr};
|
||||
Label* m_image_description{nullptr};
|
||||
wxStaticBitmap* m_image_description_icon{nullptr};
|
||||
ScalableBitmap m_description_icon_bitmap;
|
||||
|
||||
Label* m_humidity_data_label = nullptr;
|
||||
Label* m_temperature_data_label = nullptr;
|
||||
Label* m_time_data_label = nullptr;
|
||||
wxBoxSizer* m_time_descrition_container = nullptr;
|
||||
|
||||
// right panel related members
|
||||
wxBoxSizer* m_normal_state_sizer{nullptr};
|
||||
wxBoxSizer* m_cannot_dry_sizer{nullptr};
|
||||
wxBoxSizer* m_dry_error_sizer{nullptr};
|
||||
Label* m_cannot_dry_description_label = nullptr;
|
||||
|
||||
// right panel normal state
|
||||
ComboBox* m_trays_combo;
|
||||
std::vector<FilamentBaseInfo> m_tray_ids;
|
||||
wxTextCtrl* m_temperature_input;
|
||||
wxTextCtrl* m_time_input;
|
||||
Label* m_normal_description;
|
||||
Button* m_start_button{nullptr};
|
||||
Button* m_next_button{nullptr};
|
||||
Button* m_stop_button{nullptr};
|
||||
Button* m_back_button{nullptr};
|
||||
Button* m_unload_button{nullptr};
|
||||
|
||||
// guide page description
|
||||
Label* m_guide_title_label{nullptr};
|
||||
Label* m_guide_description_label{nullptr};
|
||||
|
||||
wxCheckBox* m_rotate_spool_toggle{nullptr};
|
||||
|
||||
wxPanel* m_progress_page;
|
||||
ProgressBar* m_progress_gauge;
|
||||
wxTimer* m_progress_timer;
|
||||
|
||||
std::optional<std::chrono::steady_clock::time_point> m_stop_button_restore_deadline;
|
||||
std::optional<std::chrono::steady_clock::time_point> m_unload_button_restore_deadline;
|
||||
|
||||
Label* m_progress_title;
|
||||
int m_progress_value;
|
||||
int m_progress_message_index;
|
||||
std::vector<wxString> m_progress_text = {
|
||||
_L("Starting: Checking adapter connection"),
|
||||
_L("Starting: Checking filament status"),
|
||||
_L("Starting: Checking drying presets"),
|
||||
_L("Starting: Checking filament location"),
|
||||
_L("Starting: Checking air intake"),
|
||||
_L("Starting: Checking air vent")
|
||||
};
|
||||
|
||||
// Guide page
|
||||
wxPanel* m_guide_page{nullptr};
|
||||
AMSFilamentPanel* m_ams_filament_panel{nullptr};
|
||||
std::map<std::string, FilamentItemPanel*> m_filament_items;
|
||||
wxStaticBitmap* m_image_placeholder{nullptr};
|
||||
ScalableBitmap m_guide_image;
|
||||
|
||||
|
||||
bool m_is_ams_changed = false;
|
||||
std::weak_ptr<DevFilaSystem> m_fila_system;
|
||||
struct {
|
||||
std::string m_ams_id;
|
||||
DevAmsType m_model = DevAmsType::EXT_SPOOL;
|
||||
DevAms::DryStatus m_dry_status = DevAms::DryStatus::Off;
|
||||
DevAms::DrySubStatus m_dry_sub_status = DevAms::DrySubStatus::Off;
|
||||
int m_humidity_percent;
|
||||
int m_temperature;
|
||||
int m_left_dry_time;
|
||||
float m_recommand_dry_temp;
|
||||
} m_ams_info;
|
||||
|
||||
struct {
|
||||
std::unordered_map<std::string, std::string> m_filament_names;
|
||||
std::unordered_map<std::string, std::string> m_filament_type;
|
||||
std::unordered_map<std::string, int> m_dry_temp;
|
||||
std::unordered_map<std::string, int> m_dry_time;
|
||||
} m_dry_setting;
|
||||
|
||||
struct {
|
||||
bool m_is_printing = false;
|
||||
} m_printer_status;
|
||||
|
||||
private:
|
||||
void create();
|
||||
wxBoxSizer* create_guide_page_sizer(wxPanel* parent);
|
||||
wxBoxSizer* create_main_content_section(wxPanel* parent);
|
||||
wxBoxSizer* create_guide_info_filament(wxPanel* parent);
|
||||
wxBoxSizer* create_guide_info_section(wxPanel* parent);
|
||||
wxBoxSizer* create_guide_right_section(wxPanel* parent);
|
||||
wxBoxSizer* create_main_page_sizer(wxPanel* parent);
|
||||
wxBoxSizer* create_left_panel(wxPanel* parent);
|
||||
wxBoxSizer* create_humidity_status_section(wxPanel* parent);
|
||||
wxBoxSizer* create_description_item(wxPanel* parent, const wxString& title, Label*& dataLabel);
|
||||
wxBoxSizer* create_status_descriptions_section(wxPanel* parent);
|
||||
|
||||
wxBoxSizer* create_right_panel(wxPanel* parent);
|
||||
wxBoxSizer* create_normal_state_panel(wxPanel* parent);
|
||||
wxBoxSizer* create_cannot_dry_panel(wxPanel* parent);
|
||||
wxBoxSizer* create_drying_error_panel(wxPanel* parent);
|
||||
Button* create_button(wxPanel* parent, const wxString& title,
|
||||
const wxColour& background_color, const wxColour& border_color, const wxColour& text_color);
|
||||
|
||||
wxBoxSizer* create_progress_page_sizer(wxPanel* parent);
|
||||
void OnProgressTimer(wxTimerEvent& event);
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnShow(wxShowEvent& event);
|
||||
|
||||
void OnFilamentSelectionChanged(wxCommandEvent& event);
|
||||
|
||||
|
||||
wxScrolledWindow* create_preview_scrolled_window(wxWindow* parent);
|
||||
|
||||
bool check_values_changed(DevAms* dev_ams);
|
||||
int update_image(DevAmsType type, DevAms::DryStatus status, DevAms::DrySubStatus sub_status, int humidity_percent);
|
||||
void update_img_description(DevAms::DryStatus status, DevAms::DrySubStatus sub_status);
|
||||
void update_normal_description(DevAms* dev_ams);
|
||||
int update_state(DevAms* dev_ams);
|
||||
int update_dryness_status(DevAms* dev_ams);
|
||||
int update_ams_change(DevAms* dev_ams);
|
||||
int update_filament_list(DevAms* dev_ams, MachineObject* obj);
|
||||
void update_filament_guide_info(DevAms* dev_ams);
|
||||
void update_normal_state(DevAms* dev_ams);
|
||||
void update_printer_state(MachineObject* obj);
|
||||
|
||||
std::shared_ptr<DevFilaSystem> get_fila_system() const;
|
||||
void start_sending_drying_command();
|
||||
void restore_stop_button_if_deadline_passed();
|
||||
void restore_unload_button_if_deadline_passed();
|
||||
void update_button_size(Button* button);
|
||||
|
||||
bool is_dry_status_changed(DevAms* dev_ams);
|
||||
bool is_dry_ctr_idle(DevAms* dev_ams);
|
||||
bool is_ams_changed(DevAms* dev_ams);
|
||||
bool is_dry_ctr_idle();
|
||||
bool is_tray_changed(DevAms* dev_ams);
|
||||
bool is_dry_ctr_err(DevAms* dev_ams);
|
||||
|
||||
};
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
@@ -1440,7 +1440,7 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent)
|
||||
spin_bed->SetValue(default_bed != nullptr && default_bed->size() > 0 ? default_bed->get_at(0) : 0);
|
||||
|
||||
append_text(_L("Enter the nozzle_temperature needed for extruding your filament."));
|
||||
append_text(_L("A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS."));
|
||||
append_text(_L("A rule of thumb is 160 to 230℃ for PLA, and 215 to 250℃ for ABS."));
|
||||
#endif
|
||||
|
||||
auto *sizer_extr = new wxFlexGridSizer(3, 5, 5);
|
||||
@@ -1455,7 +1455,7 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent)
|
||||
append_spacer(VERTICAL_SPACING);
|
||||
|
||||
append_text(_L("Enter the bed temperature needed for getting your filament to stick to your heated bed."));
|
||||
append_text(_L("A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have no heated bed."));
|
||||
append_text(_L("A rule of thumb is 60℃ for PLA and 110℃ for ABS. Leave zero if you have no heated bed."));
|
||||
|
||||
auto *sizer_bed = new wxFlexGridSizer(3, 5, 5);
|
||||
auto *text_bed = new wxStaticText(this, wxID_ANY, _L("Bed Temperature:"));
|
||||
|
||||
@@ -41,6 +41,16 @@ enum AmsStatusMain
|
||||
AMS_STATUS_MAIN_UNKNOWN = 0xFF,
|
||||
};
|
||||
|
||||
enum DevAmsType : int
|
||||
{
|
||||
EXT_SPOOL = 0, // EXT
|
||||
AMS = 1, // AMS1
|
||||
AMS_LITE = 2, // AMS-Lite
|
||||
N3F = 3, // N3F, AMS 2PRO
|
||||
N3S = 4, // N3S, AMS HT
|
||||
AMS_LITE_MIXED = 5, // AMS-Lite for N9
|
||||
};
|
||||
|
||||
// Device-numbered filament-change step codes. Newer firmware reports the exact change-step
|
||||
// sequence through the AMS (ams.cfs), keyed by these codes, instead of the client hardcoding
|
||||
// steps per model. Distinct from the legacy GUI-side Slic3r::GUI::FilamentStep enum.
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
|
||||
#include "DevUtil.h"
|
||||
#include "DevUtilBackend.h"
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
@@ -99,6 +100,11 @@ std::string DevAmsTray::get_filament_type()
|
||||
return m_fila_type;
|
||||
}
|
||||
|
||||
std::optional<Slic3r::DevFilamentDryingPreset> DevAmsTray::get_ams_drying_preset() const
|
||||
{
|
||||
return DevUtilBackend::GetFilamentDryingPreset(setting_id);
|
||||
}
|
||||
|
||||
|
||||
DevAms::DevAms(const std::string& ams_id, int extruder_id, AmsType type)
|
||||
{
|
||||
@@ -112,7 +118,7 @@ DevAms::DevAms(const std::string& ams_id, int nozzle_id, int type)
|
||||
m_ams_id = ams_id;
|
||||
m_ext_id = nozzle_id;
|
||||
m_ams_type = (AmsType)type;
|
||||
assert(DUMMY < type && m_ams_type <= AMS_LITE_MIXED);
|
||||
assert(EXT_SPOOL < type && m_ams_type <= AMS_LITE_MIXED);
|
||||
}
|
||||
|
||||
DevAms::~DevAms()
|
||||
@@ -193,6 +199,27 @@ DevAmsTray* DevAms::GetTray(const std::string& tray_id) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool DevAms::IsSupportRemoteDry(const MachineObject* obj) const
|
||||
{
|
||||
if (obj && obj->is_support_remote_dry) {
|
||||
return SupportDrying();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DevAms::AmsIsDrying()
|
||||
{
|
||||
if (!GetDryStatus().has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetDryStatus().value() == DevAms::DryStatus::Checking
|
||||
|| GetDryStatus().value() == DevAms::DryStatus::Drying
|
||||
|| GetDryStatus().value() == DevAms::DryStatus::Error
|
||||
|| GetDryStatus().value() == DevAms::DryStatus::CannotStopHeatOutofControl;
|
||||
}
|
||||
|
||||
DevFilaSystem::~DevFilaSystem()
|
||||
{
|
||||
for (auto it = amsList.begin(); it != amsList.end(); it++)
|
||||
@@ -515,9 +542,18 @@ void DevFilaSystemParser::ParseV1_0(const json& jj, MachineObject* obj, DevFilaS
|
||||
;
|
||||
}
|
||||
|
||||
if (it->contains("dry_time") && (*it)["dry_time"].is_number())
|
||||
|
||||
if (it->contains("temp"))
|
||||
{
|
||||
curr_ams->m_left_dry_time = (*it)["dry_time"].get<int>();
|
||||
std::string temp = (*it)["temp"].get<std::string>();
|
||||
try
|
||||
{
|
||||
curr_ams->m_current_temperature = DevUtil::string_to_float(temp);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
curr_ams->m_current_temperature = INVALID_AMS_TEMPERATURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (it->contains("humidity"))
|
||||
@@ -546,17 +582,32 @@ void DevFilaSystemParser::ParseV1_0(const json& jj, MachineObject* obj, DevFilaS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (it->contains("temp"))
|
||||
if (it->contains("dry_time") && (*it)["dry_time"].is_number())
|
||||
{
|
||||
std::string temp = (*it)["temp"].get<std::string>();
|
||||
try
|
||||
{
|
||||
curr_ams->m_current_temperature = DevUtil::string_to_float(temp);
|
||||
curr_ams->m_left_dry_time = (*it)["dry_time"].get<int>();
|
||||
}
|
||||
|
||||
// Drying status — only parse if printer supports remote drying
|
||||
if (obj->is_support_remote_dry) {
|
||||
if (it->contains("info")) {
|
||||
const std::string& info = (*it)["info"].get<std::string>();
|
||||
curr_ams->m_dry_status = (DevAms::DryStatus)DevUtil::get_flag_bits(info, 4, 4);
|
||||
curr_ams->m_dry_fan1_status = (DevAms::DryFanStatus)DevUtil::get_flag_bits(info, 18, 2);
|
||||
curr_ams->m_dry_fan2_status = (DevAms::DryFanStatus)DevUtil::get_flag_bits(info, 20, 2);
|
||||
curr_ams->m_dry_sub_status = (DevAms::DrySubStatus)DevUtil::get_flag_bits(info, 22, 2);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
curr_ams->m_current_temperature = INVALID_AMS_TEMPERATURE;
|
||||
|
||||
if (it->contains("dry_setting")) {
|
||||
const auto& j_dry_settings = (*it)["dry_setting"];
|
||||
DevAms::DrySettings dry_settings;
|
||||
DevJsonValParser::ParseVal(j_dry_settings, "dry_filament", dry_settings.dry_filament);
|
||||
DevJsonValParser::ParseVal(j_dry_settings, "dry_temperature", dry_settings.dry_temp);
|
||||
DevJsonValParser::ParseVal(j_dry_settings, "dry_duration", dry_settings.dry_hour);
|
||||
curr_ams->m_dry_settings = dry_settings;
|
||||
}
|
||||
|
||||
if (it->contains("dry_sf_reason")) {
|
||||
curr_ams->m_dry_cannot_reasons = DevJsonValParser::GetVal<std::vector<DevAms::CannotDryReason>>((*it), "dry_sf_reason");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
#include <wx/colour.h>
|
||||
|
||||
@@ -20,6 +23,7 @@
|
||||
namespace Slic3r
|
||||
{
|
||||
class MachineObject;
|
||||
struct DevFilamentDryingPreset;
|
||||
|
||||
/**
|
||||
* DevAmsTray - Represents a single filament tray/slot in an AMS unit or virtual tray.
|
||||
@@ -106,6 +110,8 @@ public:
|
||||
|
||||
// static
|
||||
static wxColour decode_color(const std::string& color);
|
||||
|
||||
std::optional<DevFilamentDryingPreset> get_ams_drying_preset() const;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -133,14 +139,67 @@ class DevAms
|
||||
{
|
||||
friend class DevFilaSystemParser;
|
||||
public:
|
||||
enum AmsType : int
|
||||
using AmsType = DevAmsType;
|
||||
static constexpr AmsType EXT_SPOOL = DevAmsType::EXT_SPOOL;
|
||||
static constexpr AmsType AMS = DevAmsType::AMS;
|
||||
static constexpr AmsType AMS_LITE = DevAmsType::AMS_LITE;
|
||||
static constexpr AmsType N3F = DevAmsType::N3F;
|
||||
static constexpr AmsType N3S = DevAmsType::N3S;
|
||||
static constexpr AmsType AMS_LITE_MIXED = DevAmsType::AMS_LITE_MIXED;
|
||||
|
||||
public:
|
||||
|
||||
enum class DryCtrlMode : int
|
||||
{
|
||||
DUMMY = 0,
|
||||
AMS = 1, // AMS
|
||||
AMS_LITE = 2, // AMS-Lite
|
||||
N3F = 3, // N3F
|
||||
N3S = 4, // N3S
|
||||
AMS_LITE_MIXED = 5, // AMS-Lite mixed (A2L / N9). Presents as AMS_LITE to generic callers; see GetAmsType()/IsAmsLiteMixed().
|
||||
Off = 0,
|
||||
OnTime = 1,
|
||||
OnHumidity = 2,
|
||||
};
|
||||
|
||||
enum class DryStatus : char
|
||||
{
|
||||
Off = 0,
|
||||
Checking = 1,
|
||||
Drying = 2,
|
||||
Cooling = 3,
|
||||
Stopping = 4,
|
||||
Error = 5,
|
||||
CannotStopHeatOutofControl = 6,
|
||||
PrdTesting = 7,
|
||||
};
|
||||
|
||||
enum class DrySubStatus
|
||||
{
|
||||
Off = 0,
|
||||
Heating = 1,
|
||||
Dehumidify = 2,
|
||||
};
|
||||
|
||||
enum class DryFanStatus : char
|
||||
{
|
||||
Off = 0,
|
||||
On = 1,
|
||||
};
|
||||
|
||||
enum class CannotDryReason : int
|
||||
{
|
||||
TaskOccupied = 0,
|
||||
InsufficientPower = 1,
|
||||
AmsBusy = 2,
|
||||
ConsumableAtAmsOutlet = 3,
|
||||
InitiatingAmsDrying = 4,
|
||||
NotSupportedIn2dMode = 5,
|
||||
DryingInProgress = 6,
|
||||
Upgrading = 7,
|
||||
InsufficientPowerNeedPluginPower = 8,
|
||||
FilamentAtAmsOutletManualUnload = 10,
|
||||
};
|
||||
|
||||
struct DrySettings
|
||||
{
|
||||
std::string dry_filament;
|
||||
int dry_temp = -1; // -1 means invalid
|
||||
int dry_hour = -1; // -1 means invalid, hours
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -193,11 +252,20 @@ public:
|
||||
int GetHumidityLevel() const { return m_humidity_level; }
|
||||
int GetHumidityPercent() const { return m_humidity_percent; }
|
||||
|
||||
// Only N3F/N3S dry. Written explicitly (not `> AMS_LITE`) so the new AMS_LITE_MIXED (N9) is
|
||||
// excluded; identical to the old expression for every pre-existing type.
|
||||
bool SupportDrying() const { return (m_ams_type == N3F) || (m_ams_type == N3S); }
|
||||
bool SupportDrying() const { return m_ams_type == DevAmsType::N3F || m_ams_type == DevAmsType::N3S; }
|
||||
int GetLeftDryTime() const { return m_left_dry_time; }
|
||||
|
||||
// remote drying control
|
||||
bool IsSupportRemoteDry(const MachineObject* obj) const;
|
||||
std::optional<DryStatus> GetDryStatus() const { return m_dry_status; };
|
||||
std::optional<DrySubStatus> GetDrySubStatus() const { return m_dry_sub_status; }
|
||||
std::optional<DryFanStatus> GetFan1Status() const { return m_dry_fan1_status; }
|
||||
std::optional<DryFanStatus> GetFan2Status() const { return m_dry_fan2_status; }
|
||||
std::optional<std::vector<CannotDryReason>> GetCannotDryReason() const { return m_dry_cannot_reasons; }
|
||||
std::optional<DrySettings> GetDrySettings() const { return m_dry_settings; };
|
||||
|
||||
bool AmsIsDrying();
|
||||
|
||||
private:
|
||||
AmsType m_ams_type = AmsType::AMS;
|
||||
std::string m_ams_id;
|
||||
@@ -218,6 +286,14 @@ private:
|
||||
int m_humidity_level = 5; // AmsType::AMS
|
||||
int m_humidity_percent = -1; // N3F N3S, the percentage, -1 means invalid. eg. 100 means 100%
|
||||
int m_left_dry_time = 0;
|
||||
|
||||
// see is_support_remote_dry
|
||||
std::optional<DryStatus> m_dry_status;
|
||||
std::optional<DrySubStatus> m_dry_sub_status;
|
||||
std::optional<DryFanStatus> m_dry_fan1_status;
|
||||
std::optional<DryFanStatus> m_dry_fan2_status;
|
||||
std::optional<std::vector<CannotDryReason>> m_dry_cannot_reasons;
|
||||
std::optional<DrySettings> m_dry_settings;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -299,7 +375,11 @@ public:
|
||||
public:
|
||||
// ctrls
|
||||
int CtrlAmsReset() const;
|
||||
|
||||
|
||||
// crtl
|
||||
int CtrlAmsStartDryingHour(int ams_id, std::string filament_type, int tag_temp, int tag_duration_hour, bool rotate_tray, int cooling_temp, bool close_power_conflict = false) const;
|
||||
int CtrlAmsStopDrying(int ams_id) const;
|
||||
|
||||
public:
|
||||
static bool IsBBL_Filament(std::string tag_uid);
|
||||
|
||||
@@ -339,4 +419,18 @@ public:
|
||||
static void ParseAgentFilament(const json& data, MachineObject* obj, DevFilaSystem* system);
|
||||
};
|
||||
|
||||
struct DevFilamentDryingPreset
|
||||
{
|
||||
std::string filament_id;
|
||||
|
||||
std::unordered_set<DevAmsType> ams_limitations; // only use ams types in the set
|
||||
std::unordered_map<DevAmsType, float> filament_dev_ams_drying_time_on_idle; // hour
|
||||
std::unordered_map<DevAmsType, float> filament_dev_ams_drying_temperature_on_idle;
|
||||
std::unordered_map<DevAmsType, float> filament_dev_ams_drying_time_on_print; // hour
|
||||
std::unordered_map<DevAmsType, float> filament_dev_ams_drying_temperature_on_print;
|
||||
float filament_dev_drying_cooling_temperature = 0.0f;
|
||||
float filament_dev_drying_softening_temperature = 0.0f;
|
||||
float filament_dev_ams_drying_heat_distortion_temperature = 0.0f;
|
||||
};
|
||||
|
||||
}// namespace Slic3r
|
||||
@@ -16,4 +16,44 @@ int DevFilaSystem::CtrlAmsReset() const
|
||||
return m_owner->publish_json(jj_command);
|
||||
}
|
||||
|
||||
int DevFilaSystem::CtrlAmsStartDryingHour(int ams_id,
|
||||
std::string filament_type,
|
||||
int tag_temp,
|
||||
int tag_duration_hour,
|
||||
bool rotate_tray,
|
||||
int cooling_temp,
|
||||
bool close_power_conflict) const
|
||||
{
|
||||
json jj_command;
|
||||
jj_command["print"]["command"] = "ams_filament_drying";
|
||||
jj_command["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
jj_command["print"]["ams_id"] = ams_id;
|
||||
jj_command["print"]["mode"] = static_cast<int>(DevAms::DryCtrlMode::OnTime);
|
||||
jj_command["print"]["filament"] = filament_type;
|
||||
jj_command["print"]["temp"] = tag_temp;
|
||||
jj_command["print"]["duration"] = tag_duration_hour;
|
||||
jj_command["print"]["humidity"] = 0;
|
||||
jj_command["print"]["rotate_tray"] = rotate_tray;
|
||||
jj_command["print"]["cooling_temp"] = cooling_temp;
|
||||
jj_command["print"]["close_power_conflict"] = close_power_conflict;
|
||||
return m_owner->publish_json(jj_command);
|
||||
}
|
||||
|
||||
int DevFilaSystem::CtrlAmsStopDrying(int ams_id) const
|
||||
{
|
||||
json jj_command;
|
||||
jj_command["print"]["command"] = "ams_filament_drying";
|
||||
jj_command["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
jj_command["print"]["ams_id"] = ams_id;
|
||||
jj_command["print"]["mode"] = static_cast<int>(DevAms::DryCtrlMode::Off);
|
||||
jj_command["print"]["filament"] = "";
|
||||
jj_command["print"]["temp"] = 0;
|
||||
jj_command["print"]["duration"] = 0;
|
||||
jj_command["print"]["humidity"] = 0;
|
||||
jj_command["print"]["rotate_tray"] = false;
|
||||
jj_command["print"]["cooling_temp"] = 0;
|
||||
jj_command["print"]["close_power_conflict"] = false;
|
||||
return m_owner->publish_json(jj_command);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -199,7 +199,7 @@ namespace Slic3r
|
||||
}
|
||||
}
|
||||
FilamentInfo info;
|
||||
_parse_tray_info(atoi(tray.id.c_str()), 0, DevAms::DUMMY, tray, info);
|
||||
_parse_tray_info(atoi(tray.id.c_str()), 0, DevAms::EXT_SPOOL, tray, info);
|
||||
tray_filaments.emplace(std::make_pair(info.tray_id, info));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include "DevUtilBackend.h"
|
||||
|
||||
#include "slic3r/GUI/BackgroundSlicingProcess.hpp"
|
||||
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
@@ -15,4 +19,68 @@ std::shared_ptr<MultiNozzleUtils::NozzleGroupResultBase> DevUtilBackend::GetNozz
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::unordered_map<std::string, DevAmsType> s_ams_type_map = {
|
||||
{"0", DevAmsType::N3F},
|
||||
{"1", DevAmsType::N3S},
|
||||
};
|
||||
|
||||
std::optional<Slic3r::DevFilamentDryingPreset> DevUtilBackend::GetFilamentDryingPreset(const std::string& fila_id)
|
||||
{
|
||||
if (fila_id.empty() || !GUI::wxGetApp().preset_bundle) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for (auto iter = GUI::wxGetApp().preset_bundle->filaments.begin(); iter != GUI::wxGetApp().preset_bundle->filaments.end(); ++iter) {
|
||||
const Preset& filament_preset = *iter;
|
||||
const auto& config = filament_preset.config;
|
||||
if (filament_preset.filament_id == fila_id) {
|
||||
DevFilamentDryingPreset info;
|
||||
info.filament_id = fila_id;
|
||||
try {
|
||||
if (config.has("filament_dev_ams_drying_ams_limitations")) {
|
||||
std::vector<std::string> types = config.option<ConfigOptionStrings>("filament_dev_ams_drying_ams_limitations")->values;
|
||||
for (auto type : types) {
|
||||
if (s_ams_type_map.count(type) == 0) {
|
||||
continue;
|
||||
}
|
||||
info.ams_limitations.insert(s_ams_type_map[type]);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.has("filament_dev_ams_drying_temperature")) {
|
||||
info.filament_dev_ams_drying_temperature_on_idle[DevAmsType::N3F] = config.option<ConfigOptionFloats>("filament_dev_ams_drying_temperature")->get_at(0);
|
||||
info.filament_dev_ams_drying_temperature_on_idle[DevAmsType::N3S] = config.option<ConfigOptionFloats>("filament_dev_ams_drying_temperature")->get_at(1);
|
||||
info.filament_dev_ams_drying_temperature_on_print[DevAmsType::N3F] = config.option<ConfigOptionFloats>("filament_dev_ams_drying_temperature")->get_at(2);
|
||||
info.filament_dev_ams_drying_temperature_on_print[DevAmsType::N3S] = config.option<ConfigOptionFloats>("filament_dev_ams_drying_temperature")->get_at(3);
|
||||
}
|
||||
|
||||
if (config.has("filament_dev_ams_drying_time")) {
|
||||
info.filament_dev_ams_drying_time_on_idle[DevAmsType::N3F] = config.option<ConfigOptionFloats>("filament_dev_ams_drying_time")->get_at(0);
|
||||
info.filament_dev_ams_drying_time_on_idle[DevAmsType::N3S] = config.option<ConfigOptionFloats>("filament_dev_ams_drying_time")->get_at(1);
|
||||
info.filament_dev_ams_drying_time_on_print[DevAmsType::N3F] = config.option<ConfigOptionFloats>("filament_dev_ams_drying_time")->get_at(2);
|
||||
info.filament_dev_ams_drying_time_on_print[DevAmsType::N3S] = config.option<ConfigOptionFloats>("filament_dev_ams_drying_time")->get_at(3);
|
||||
}
|
||||
|
||||
if (config.has("filament_dev_drying_softening_temperature")) {
|
||||
info.filament_dev_drying_softening_temperature = config.option<ConfigOptionFloats>("filament_dev_drying_softening_temperature")->get_at(0);
|
||||
}
|
||||
|
||||
if (config.has("filament_dev_ams_drying_heat_distortion_temperature")) {
|
||||
info.filament_dev_ams_drying_heat_distortion_temperature = config.option<ConfigOptionFloats>("filament_dev_ams_drying_heat_distortion_temperature")->get_at(0);
|
||||
}
|
||||
|
||||
if (config.has("filament_dev_drying_cooling_temperature")) {
|
||||
info.filament_dev_drying_cooling_temperature = config.option<ConfigOptionFloats>("filament_dev_drying_cooling_temperature")->get_at(0);
|
||||
}
|
||||
|
||||
return info;
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " exception: " << e.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
/**
|
||||
* @file DevUtilBackend.h
|
||||
* @brief Static helpers bridging the backend (slicer/preset) to the device GUI.
|
||||
*
|
||||
* Scope (H2C nozzle rack): exposes only GetNozzleGroupResult — the accessor the print-dispatch
|
||||
* nozzle-mapping V1 request and result-resolve helpers read. Related helpers (per-nozzle info
|
||||
* collection via the ExtruderNozzleInfos/NozzleDef type pair, and the drying-preset lookup) are
|
||||
* not implemented here and left to the consuming code.
|
||||
* @brief Provides common static utility methods for backend (preset/slicing).
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "DevDefs.h"
|
||||
#include "DevFilaSystem.h"
|
||||
|
||||
#include "libslic3r/MultiNozzleUtils.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
@@ -23,10 +20,15 @@ class DevUtilBackend
|
||||
public:
|
||||
DevUtilBackend() = delete;
|
||||
|
||||
public:
|
||||
|
||||
// for rack: the slicer's per-filament -> logical-nozzle grouping for the current plate, read off
|
||||
// the post-slice GCodeProcessorResult (plater->background_process().get_current_gcode_result()).
|
||||
// Returns nullptr when there is no plater / no current result.
|
||||
static std::shared_ptr<MultiNozzleUtils::NozzleGroupResultBase> GetNozzleGroupResult(Slic3r::GUI::Plater* plater);
|
||||
|
||||
// for filament preset
|
||||
static std::optional<DevFilamentDryingPreset> GetFilamentDryingPreset(const std::string& fila_id);
|
||||
};
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
@@ -568,7 +568,7 @@ MachineObject::MachineObject(DeviceManager* manager, NetworkAgent* agent, std::s
|
||||
m_extder_system = new DevExtderSystem(this);
|
||||
m_extension_tool = DevExtensionTool::Create(this);
|
||||
m_nozzle_system = new DevNozzleSystem(this);
|
||||
m_fila_system = new DevFilaSystem(this);
|
||||
m_fila_system = std::make_shared<DevFilaSystem>(this);
|
||||
m_fila_switch = new DevFilaSwitch(this);
|
||||
m_hms_system = new DevHMS(this);
|
||||
m_config = new DevConfig(this);
|
||||
@@ -617,8 +617,6 @@ MachineObject::~MachineObject()
|
||||
delete m_ctrl;
|
||||
m_ctrl = nullptr;
|
||||
|
||||
delete m_fila_system;
|
||||
m_fila_system = nullptr;
|
||||
|
||||
delete m_fila_switch;
|
||||
m_fila_switch = nullptr;
|
||||
@@ -3770,7 +3768,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
||||
update_printer_preset_name();
|
||||
update_filament_list();
|
||||
if (jj.contains("ams")) {
|
||||
DevFilaSystemParser::ParseV1_0(jj, this, m_fila_system, key_field_only);
|
||||
DevFilaSystemParser::ParseV1_0(jj, this, m_fila_system.get(), key_field_only);
|
||||
}
|
||||
|
||||
/* vitrual tray*/
|
||||
@@ -5095,6 +5093,7 @@ void MachineObject::parse_new_info(json print)
|
||||
// fun2 may have infinite length, use get_flag_bits_no_border
|
||||
if (!fun2.empty()) {
|
||||
is_support_print_with_emmc = get_flag_bits_no_border(fun2, 0) == 1;
|
||||
is_support_remote_dry = (get_flag_bits_no_border(fun2, 5) == 1);
|
||||
is_support_check_track_switch_match_slice_printer = get_flag_bits_no_border(fun2, 19) == 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ private:
|
||||
std::shared_ptr<DevExtensionTool> m_extension_tool;
|
||||
DevExtderSystem* m_extder_system;
|
||||
DevNozzleSystem* m_nozzle_system;
|
||||
DevFilaSystem* m_fila_system;
|
||||
std::shared_ptr<DevFilaSystem> m_fila_system;
|
||||
DevFilaSwitch* m_fila_switch;
|
||||
DevFan* m_fan;
|
||||
DevBed * m_bed;
|
||||
@@ -342,7 +342,7 @@ public:
|
||||
std::shared_ptr<DevNozzleMappingCtrl> get_nozzle_mapping_result() const { return m_nozzle_mapping_ptr; }
|
||||
void clear_auto_nozzle_mapping();// defined in DevMappingNozzle.cpp
|
||||
|
||||
DevFilaSystem* GetFilaSystem() const { return m_fila_system;}
|
||||
std::shared_ptr<DevFilaSystem> GetFilaSystem() const { return m_fila_system;}
|
||||
DevFilaSwitch* GetFilaSwitch() const { return m_fila_switch;}
|
||||
bool HasAms() const;
|
||||
|
||||
@@ -635,6 +635,7 @@ public:
|
||||
|
||||
// fun2
|
||||
bool is_support_print_with_emmc{false};
|
||||
bool is_support_remote_dry = false;
|
||||
bool is_support_check_track_switch_match_slice_printer{false};
|
||||
|
||||
bool installed_upgrade_kit{false};
|
||||
|
||||
@@ -445,7 +445,7 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
add_row(_u8L("Flow rate"), buff);
|
||||
sprintf(buff, "%.0f %%", vertex.fan_speed);
|
||||
add_row(_u8L("Fan speed"), buff);
|
||||
sprintf(buff, ("%.0f " + _u8L("°C")).c_str(), vertex.temperature);
|
||||
sprintf(buff, ("%.0f " + _u8L("\u2103" /* °C */)).c_str(), vertex.temperature);
|
||||
add_row(_u8L("Temperature"), buff);
|
||||
sprintf(buff, "%.4f", vertex.pressure_advance);
|
||||
add_row(_u8L("Pressure Advance"), buff);
|
||||
@@ -3711,7 +3711,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::FanSpeed: { imgui.title(_u8L("Fan speed (%)")); break; }
|
||||
case libvgcode::EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; }
|
||||
case libvgcode::EViewType::Temperature: { imgui.title(_u8L("Temperature (℃)")); break; }
|
||||
// ORCA: Add Pressure Advance visualization support
|
||||
case libvgcode::EViewType::PressureAdvance:{ imgui.title(_u8L("Pressure Advance")); break; }
|
||||
case libvgcode::EViewType::VolumetricFlowRate:
|
||||
|
||||
@@ -2338,11 +2338,6 @@ void GLCanvas3D::remove_curr_plate_all()
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GLCanvas3D::update_plate_thumbnails()
|
||||
{
|
||||
_update_imgui_select_plate_toolbar();
|
||||
}
|
||||
|
||||
void GLCanvas3D::select_all()
|
||||
{
|
||||
if (!m_gizmos.is_allow_select_all()) {
|
||||
@@ -3228,7 +3223,6 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
||||
// BBS
|
||||
//m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state();
|
||||
m_dirty |= wxGetApp().plater()->get_collapse_toolbar().update_items_state();
|
||||
_update_imgui_select_plate_toolbar();
|
||||
bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera());
|
||||
m_dirty |= mouse3d_controller_applied;
|
||||
m_dirty |= wxGetApp().plater()->get_notification_manager()->update_notifications(*this);
|
||||
@@ -4838,11 +4832,6 @@ void GLCanvas3D::force_set_focus() {
|
||||
void GLCanvas3D::on_set_focus(wxFocusEvent& evt)
|
||||
{
|
||||
m_tooltip_enabled = false;
|
||||
if (m_canvas_type == ECanvasType::CanvasPreview) {
|
||||
// update thumbnails and update plate toolbar
|
||||
wxGetApp().plater()->update_all_plate_thumbnails();
|
||||
_update_imgui_select_plate_toolbar();
|
||||
}
|
||||
_refresh_if_shown_on_screen();
|
||||
m_tooltip_enabled = true;
|
||||
m_is_touchpad_navigation = wxGetApp().app_config->get_bool("camera_navigation_style");
|
||||
@@ -6925,13 +6914,28 @@ void GLCanvas3D::_update_select_plate_toolbar_stats_item(bool force_selected) {
|
||||
bool GLCanvas3D::_update_imgui_select_plate_toolbar()
|
||||
{
|
||||
bool result = true;
|
||||
if (!m_sel_plate_toolbar.is_enabled() || m_sel_plate_toolbar.is_render_finish) return false;
|
||||
if (!m_sel_plate_toolbar.is_enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& p_plater = wxGetApp().plater();
|
||||
if (!p_plater) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!p_plater->is_plate_toolbar_image_dirty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!p_plater->is_gcode_3mf()) {
|
||||
p_plater->update_all_plate_thumbnails(true);
|
||||
}
|
||||
|
||||
_update_select_plate_toolbar_stats_item();
|
||||
|
||||
m_sel_plate_toolbar.del_all_item();
|
||||
|
||||
PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
|
||||
PartPlateList& plate_list = p_plater->get_partplate_list();
|
||||
for (int i = 0; i < plate_list.get_plate_count(); i++) {
|
||||
IMToolbarItem* item = new IMToolbarItem();
|
||||
PartPlate* plate = plate_list.get_plate(i);
|
||||
@@ -6944,7 +6948,7 @@ bool GLCanvas3D::_update_imgui_select_plate_toolbar()
|
||||
}
|
||||
m_sel_plate_toolbar.m_items.push_back(item);
|
||||
}
|
||||
|
||||
p_plater->clear_plate_toolbar_image_dirty();
|
||||
m_sel_plate_toolbar.is_display_scrollbar = false;
|
||||
return result;
|
||||
}
|
||||
@@ -8802,6 +8806,8 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
|
||||
return;
|
||||
}
|
||||
|
||||
_update_imgui_select_plate_toolbar();
|
||||
|
||||
IMToolbarItem* all_plates_stats_item = m_sel_plate_toolbar.m_all_plates_stats_item;
|
||||
|
||||
PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
|
||||
@@ -9218,7 +9224,6 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
|
||||
m_sel_plate_toolbar.is_display_scrollbar = is_win_hovered;
|
||||
|
||||
imgui.end();
|
||||
m_sel_plate_toolbar.is_render_finish = true;
|
||||
}
|
||||
|
||||
//BBS: GUI refactor: GLToolbar adjust
|
||||
|
||||
@@ -997,7 +997,6 @@ public:
|
||||
void select_curr_plate_all();
|
||||
void select_object_from_idx(std::vector<int>& object_idxs);
|
||||
void remove_curr_plate_all();
|
||||
void update_plate_thumbnails();
|
||||
|
||||
void select_all();
|
||||
void deselect_all();
|
||||
|
||||
+25
-15
@@ -4775,7 +4775,7 @@ void GUI_App::request_user_logout(const std::string& provider/* = ORCA_CLOUD_PRO
|
||||
remove_user_presets();
|
||||
enable_user_preset_folder(false);
|
||||
Slic3r::PluginManager::instance().unload_cloud_plugins();
|
||||
Slic3r::PluginManager::instance().clear_cloud_plugin_catalog();
|
||||
Slic3r::PluginManager::instance().clear_cloud_plugin_metadata();
|
||||
Slic3r::PluginManager::instance().set_cloud_user("");
|
||||
preset_bundle->load_user_presets(DEFAULT_USER_FOLDER_NAME, ForwardCompatibilitySubstitutionRule::Enable);
|
||||
mainframe->update_side_preset_ui();
|
||||
@@ -8255,22 +8255,32 @@ void GUI_App::open_plugins_dialog(size_t open_on_tab, const std::string& highlig
|
||||
|
||||
void GUI_App::open_terminal_dialog()
|
||||
{
|
||||
if (m_terminal_dlg) {
|
||||
// Reached from the plugins dialog's webview ("open_terminal" command), i.e. from
|
||||
// inside the webview script-message callback, which GTK/macOS deliver synchronously
|
||||
// (see ui_create_window in PluginHostUi.cpp). TerminalDialog hosts a webview of its
|
||||
// own, so creating or presenting it on that stack is the same class as the Linux
|
||||
// gtk_window_present crash — defer all window work to a clean main-loop iteration.
|
||||
CallAfter([this]() {
|
||||
if (m_terminal_dlg) {
|
||||
// Re-front the existing window; guard Show() per #13657 (GTK re-enters
|
||||
// layout when showing an already-visible window).
|
||||
if (!m_terminal_dlg->IsShown())
|
||||
m_terminal_dlg->Show();
|
||||
m_terminal_dlg->Raise();
|
||||
return;
|
||||
}
|
||||
|
||||
m_terminal_dlg = new TerminalDialog(mainframe, wxID_ANY, _L("Plugin Terminal"),
|
||||
wxDefaultPosition, wxSize(820, 600));
|
||||
m_terminal_dlg->Bind(wxEVT_DESTROY, [this](wxWindowDestroyEvent& event) {
|
||||
if (event.GetEventObject() == m_terminal_dlg)
|
||||
m_terminal_dlg = nullptr;
|
||||
event.Skip();
|
||||
});
|
||||
|
||||
// Show() alone activates and fronts a freshly created window on every platform.
|
||||
m_terminal_dlg->Show();
|
||||
m_terminal_dlg->Raise();
|
||||
return;
|
||||
}
|
||||
|
||||
m_terminal_dlg = new TerminalDialog(mainframe, wxID_ANY, _L("Plugin Terminal"),
|
||||
wxDefaultPosition, wxSize(820, 600));
|
||||
m_terminal_dlg->Bind(wxEVT_DESTROY, [this](wxWindowDestroyEvent& event) {
|
||||
if (event.GetEventObject() == m_terminal_dlg)
|
||||
m_terminal_dlg = nullptr;
|
||||
event.Skip();
|
||||
});
|
||||
|
||||
m_terminal_dlg->Show();
|
||||
m_terminal_dlg->Raise();
|
||||
}
|
||||
|
||||
void GUI_App::open_exportpresetbundledialog(size_t open_on_tab, const std::string& highlight_option)
|
||||
|
||||
@@ -61,8 +61,6 @@ void IMToolbar::del_stats_item()
|
||||
void IMToolbar::set_enabled(bool enable)
|
||||
{
|
||||
m_enabled = enable;
|
||||
if (!m_enabled)
|
||||
is_render_finish = false;
|
||||
}
|
||||
|
||||
bool IMReturnToolbar::init()
|
||||
|
||||
@@ -51,7 +51,6 @@ public:
|
||||
float icon_height;
|
||||
bool is_display_scrollbar;
|
||||
bool show_stats_item{ false };
|
||||
bool is_render_finish{false};
|
||||
IMToolbar() {
|
||||
icon_width = DEFAULT_TOOLBAR_BUTTON_WIDTH;
|
||||
icon_height = DEFAULT_TOOLBAR_BUTTON_HEIGHT;
|
||||
|
||||
@@ -3158,6 +3158,9 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
|
||||
shader->set_uniform("Texture", 0);
|
||||
shader->set_uniform("ProjMtx", ortho_projection);
|
||||
|
||||
const uint8_t stage = 0;
|
||||
shader->set_uniform("s_texture", stage);
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
const ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
const ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||
@@ -3222,6 +3225,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
|
||||
glsafe(::glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)));
|
||||
|
||||
// Bind texture, Draw
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0 + stage));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
|
||||
glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))));
|
||||
}
|
||||
|
||||
@@ -348,6 +348,8 @@ void FillBedJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||
}
|
||||
m_plater->update();
|
||||
}
|
||||
|
||||
m_plater->mark_plate_toolbar_image_dirty();
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
@@ -266,7 +266,12 @@ bool OpenGLManager::init_gl(bool popup_error)
|
||||
else
|
||||
s_compressed_textures_supported = false;
|
||||
|
||||
if (GLAD_GL_ARB_framebuffer_object) {
|
||||
if (s_gl_info.is_version_greater_or_equal_to(3, 0)) {
|
||||
// ARB framebuffer became a mandatory part of core OpenGL 3.0
|
||||
s_framebuffers_type = EFramebufferType::Arb;
|
||||
BOOST_LOG_TRIVIAL(info) << "Opengl version >= 30, FrameBuffer Type ARB." << std::endl;
|
||||
}
|
||||
else if (GLAD_GL_ARB_framebuffer_object) {
|
||||
s_framebuffers_type = EFramebufferType::Arb;
|
||||
BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type ARB."<< std::endl;
|
||||
}
|
||||
|
||||
@@ -2433,6 +2433,9 @@ void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height
|
||||
m_depth = depth;
|
||||
m_height = height;
|
||||
|
||||
if (with_instance_move && m_plater)
|
||||
m_plater->mark_plate_toolbar_image_dirty();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2780,6 +2783,8 @@ int PartPlate::add_instance(int obj_id, int instance_id, bool move_position, Bou
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1% , m_ready_for_slice changes to %2%") % m_plate_index %m_ready_for_slice;
|
||||
if (m_plater)
|
||||
m_plater->mark_plate_toolbar_image_dirty();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5344,6 +5349,9 @@ int PartPlateList::notify_instance_removed(int obj_id, int instance_id)
|
||||
unprintable_plate.update_object_index(obj_id, m_model->objects.size());
|
||||
}
|
||||
|
||||
if (m_plater)
|
||||
m_plater->mark_plate_toolbar_image_dirty();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6265,6 +6273,9 @@ int PartPlateList::rebuild_plates_after_arrangement(bool recycle_plates, bool ex
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_plater)
|
||||
m_plater->mark_plate_toolbar_image_dirty();
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":after rebuild, plates count %1%") % m_plate_list.size();
|
||||
return ret;
|
||||
}
|
||||
|
||||
+31
-10
@@ -290,6 +290,21 @@ void Plater::show_illegal_characters_warning(wxWindow* parent)
|
||||
show_error(parent, _L("Invalid name, the following characters are not allowed:") + " <>:/\\|?*\"");
|
||||
}
|
||||
|
||||
void Plater::mark_plate_toolbar_image_dirty()
|
||||
{
|
||||
m_b_plate_toolbar_image_dirty = true;
|
||||
}
|
||||
|
||||
bool Plater::is_plate_toolbar_image_dirty() const
|
||||
{
|
||||
return m_b_plate_toolbar_image_dirty;
|
||||
}
|
||||
|
||||
void Plater::clear_plate_toolbar_image_dirty()
|
||||
{
|
||||
m_b_plate_toolbar_image_dirty = false;
|
||||
}
|
||||
|
||||
static std::map<BedType, std::string> bed_type_thumbnails = {
|
||||
{BedType::btPC, "bed_cool" },
|
||||
{BedType::btEP, "bed_engineering" },
|
||||
@@ -6348,10 +6363,8 @@ void Plater::priv::update(unsigned int flags)
|
||||
//BBS assemble view
|
||||
this->assemble_view->reload_scene(false, flags);
|
||||
|
||||
if (current_panel && is_preview_shown()) {
|
||||
q->force_update_all_plate_thumbnails();
|
||||
//update_fff_scene_only_shells(true);
|
||||
}
|
||||
// todo: better to mark thumbnail dirty here
|
||||
q->mark_plate_toolbar_image_dirty();
|
||||
|
||||
if (force_background_processing_restart)
|
||||
this->restart_background_process(update_status);
|
||||
@@ -7906,6 +7919,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
}
|
||||
}
|
||||
q->schedule_background_process(true);
|
||||
q->mark_plate_toolbar_image_dirty();
|
||||
return obj_idxs;
|
||||
}
|
||||
|
||||
@@ -8285,6 +8299,8 @@ void Plater::priv::object_list_changed()
|
||||
main_frame->update_slice_print_status(MainFrame::eEventObjectUpdate, can_slice);
|
||||
|
||||
wxGetApp().params_panel()->notify_object_config_changed();
|
||||
|
||||
q->mark_plate_toolbar_image_dirty();
|
||||
}
|
||||
|
||||
void Plater::priv::select_curr_plate_all()
|
||||
@@ -9188,6 +9204,8 @@ void Plater::priv::update_fff_scene()
|
||||
view3D->reload_scene(true);
|
||||
//BBS: add assemble view related logic
|
||||
assemble_view->reload_scene(true);
|
||||
|
||||
q->mark_plate_toolbar_image_dirty();
|
||||
}
|
||||
|
||||
//BBS: add print project related logic
|
||||
@@ -10096,9 +10114,6 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
|
||||
preview->get_canvas3d()->enable_select_plate_toolbar(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
preview->get_canvas3d()->enable_select_plate_toolbar(false);
|
||||
}
|
||||
|
||||
if (current_panel == panel)
|
||||
{
|
||||
@@ -10957,6 +10972,7 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":finished, reload print soon");
|
||||
m_is_slicing = false;
|
||||
this->preview->reload_print(false);
|
||||
q->mark_plate_toolbar_image_dirty();
|
||||
/* BBS if in publishing progress */
|
||||
if (m_is_publishing) {
|
||||
if (m_publish_dlg && !m_publish_dlg->was_cancelled()) {
|
||||
@@ -13940,8 +13956,13 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i
|
||||
_obj->config.set_key_value("seam_slope_type", new ConfigOptionEnum<SeamScarfType>(SeamScarfType::None));
|
||||
_obj->config.set_key_value("gap_fill_target", new ConfigOptionEnum<GapFillTarget>(GapFillTarget::gftNowhere));
|
||||
print_config->set_key_value("max_volumetric_extrusion_rate_slope", new ConfigOptionFloat(0));
|
||||
// ORCA: print the top surface spiral from the center outwards, so the tiles are comparable.
|
||||
_obj->config.set_key_value("top_surface_fill_order", new ConfigOptionEnum<SurfaceFillOrder>(SurfaceFillOrder::Outward));
|
||||
// ORCA: request the calibration's special toolpath order (chords first, center spiral
|
||||
// last and inside-out) so opposing directions collide into the tactile lip the test
|
||||
// reads. The special order only applies while the fill order is Default, so reset the
|
||||
// profile's fill order on the calibration objects; changing the setting on the object
|
||||
// afterwards deliberately overrides the special order.
|
||||
_obj->config.set_key_value("calib_flowrate_topinfill_special_order", new ConfigOptionBool(true));
|
||||
_obj->config.set_key_value("top_surface_fill_order", new ConfigOptionEnum<SurfaceFillOrder>(SurfaceFillOrder::Default));
|
||||
|
||||
// extract flowrate from name, filename format: flowrate_xxx
|
||||
std::string obj_name = _obj->name;
|
||||
@@ -14678,6 +14699,7 @@ void Plater::invalid_all_plate_thumbnails()
|
||||
plate->thumbnail_data.reset();
|
||||
plate->no_light_thumbnail_data.reset();
|
||||
}
|
||||
mark_plate_toolbar_image_dirty();
|
||||
}
|
||||
|
||||
void Plater::force_update_all_plate_thumbnails()
|
||||
@@ -14688,7 +14710,6 @@ void Plater::force_update_all_plate_thumbnails()
|
||||
invalid_all_plate_thumbnails();
|
||||
update_all_plate_thumbnails(true);
|
||||
}
|
||||
get_preview_canvas3D()->update_plate_thumbnails();
|
||||
}
|
||||
|
||||
// BBS: backup
|
||||
|
||||
@@ -955,6 +955,10 @@ public:
|
||||
|
||||
bool is_loading_project() const { return m_loading_project; }
|
||||
|
||||
void mark_plate_toolbar_image_dirty();
|
||||
bool is_plate_toolbar_image_dirty() const;
|
||||
void clear_plate_toolbar_image_dirty();
|
||||
|
||||
private:
|
||||
struct priv;
|
||||
std::unique_ptr<priv> p;
|
||||
@@ -975,6 +979,7 @@ private:
|
||||
std::string m_preview_only_filename;
|
||||
int m_valid_plates_count { 0 };
|
||||
int m_check_status = 0; // 0 not check, 1 check success, 2 check failed
|
||||
bool m_b_plate_toolbar_image_dirty{ true };
|
||||
|
||||
void suppress_snapshots();
|
||||
void allow_snapshots();
|
||||
|
||||
@@ -163,14 +163,6 @@ PluginWebDialog* PluginWebDialog::create_modeless_dialog(wxWindow* parent,
|
||||
std::move(on_destroyed));
|
||||
}
|
||||
|
||||
void PluginWebDialog::show_modeless_dialog(PluginWebDialog* dialog)
|
||||
{
|
||||
if (dialog == nullptr)
|
||||
return;
|
||||
dialog->Show();
|
||||
dialog->Raise();
|
||||
}
|
||||
|
||||
void PluginWebDialog::post_message(PluginWebDialog* dialog, const nlohmann::json& data)
|
||||
{
|
||||
if (dialog != nullptr && dialog->is_open())
|
||||
|
||||
@@ -52,7 +52,6 @@ public:
|
||||
MessageHandler on_message,
|
||||
CloseHandler on_close,
|
||||
CloseHandler on_destroyed);
|
||||
static void show_modeless_dialog(PluginWebDialog* dialog);
|
||||
static void post_message(PluginWebDialog* dialog, const nlohmann::json& data);
|
||||
static void request_close(PluginWebDialog* dialog);
|
||||
|
||||
|
||||
@@ -116,8 +116,8 @@ struct PluginDialogItem
|
||||
PluginAvailableActions available_actions;
|
||||
};
|
||||
|
||||
constexpr bool kFetchCloudCatalog = true;
|
||||
constexpr bool kUseCurrentCloudCatalog = false;
|
||||
constexpr bool kFetchCloudMeta = true;
|
||||
constexpr bool kUseCurrentCloudMeta = false;
|
||||
|
||||
// The type of a package's first loaded capability. A package that is not loaded has no type.
|
||||
PluginCapabilityType primary_capability_type_of(PluginManager& manager, const std::string& plugin_key)
|
||||
@@ -126,7 +126,7 @@ PluginCapabilityType primary_capability_type_of(PluginManager& manager, const st
|
||||
return capabilities.empty() ? PluginCapabilityType::Unknown : capabilities.front()->type();
|
||||
}
|
||||
|
||||
std::vector<PluginDescriptor> current_cloud_catalog_snapshot()
|
||||
std::vector<PluginDescriptor> current_cloud_metadata_snapshot()
|
||||
{
|
||||
std::vector<PluginDescriptor> cloud_entries;
|
||||
for (const PluginDescriptor& entry : PluginManager::instance().get_plugin_descriptors(/*include_invalid=*/true))
|
||||
@@ -147,20 +147,18 @@ PluginDescriptor as_cloud_only_descriptor(PluginDescriptor descriptor)
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// rescan_plugins() clears the whole catalog and rediscovers only local packages, so when no fresh cloud
|
||||
// data is needed, restore the current cloud rows afterwards or cloud-only rows would disappear.
|
||||
void refresh_plugin_catalog_blocking(bool fetch_cloud)
|
||||
void refresh_plugin_metadata_blocking(bool fetch_cloud)
|
||||
{
|
||||
PluginManager& manager = PluginManager::instance();
|
||||
|
||||
std::vector<std::string> not_found, unauthorized;
|
||||
const std::vector<PluginDescriptor> current_cloud_catalog = fetch_cloud ? std::vector<PluginDescriptor>{} :
|
||||
current_cloud_catalog_snapshot();
|
||||
const std::vector<PluginDescriptor> current_cloud_metadata = fetch_cloud ? std::vector<PluginDescriptor>{} :
|
||||
current_cloud_metadata_snapshot();
|
||||
|
||||
manager.rescan_plugins();
|
||||
|
||||
if (!fetch_cloud) {
|
||||
manager.update_cloud_catalog(current_cloud_catalog);
|
||||
manager.update_cloud_metadata(current_cloud_metadata);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -450,7 +448,7 @@ void PluginsDialog::set_open_terminal_dlg_fn()
|
||||
|
||||
void PluginsDialog::update_plugin_dialog_ui()
|
||||
{
|
||||
// Called after the shared catalog is already updated, for example from the
|
||||
// Called after the any metadata is already updated, for example from the
|
||||
// cloud-plugin state callback. Do not fetch here or the callback can re-enter.
|
||||
send_plugins();
|
||||
resolve_pending_activation();
|
||||
@@ -482,10 +480,21 @@ void PluginsDialog::on_script_message(const nlohmann::json& payload)
|
||||
if (handle_common_script_command(payload))
|
||||
return;
|
||||
|
||||
// Defer command handling out of the webview script-message callback: GTK and macOS
|
||||
// deliver it synchronously inside the native webview callback (see ui_create_window
|
||||
// in PluginHostUi.cpp), and window work on that stack is the crash class fixed in
|
||||
// b779a7bfed/f2ccbfc8b5. Deferring at this single entry point keeps every command
|
||||
// handler, current and future, off that stack by construction.
|
||||
wxGetApp().CallAfter([this, alive = m_alive, payload]() {
|
||||
if (alive->load(std::memory_order_acquire))
|
||||
handle_web_command(payload);
|
||||
});
|
||||
}
|
||||
|
||||
void PluginsDialog::handle_web_command(const nlohmann::json& payload)
|
||||
{
|
||||
const std::string command = payload.value("command", "");
|
||||
if (command == "request_plugins") {
|
||||
// Discovery already runs at startup and on login, so the shared catalog is up to date by the
|
||||
// time the dialog opens: render it without a blocking fetch. Refresh is what rediscovers.
|
||||
send_plugins();
|
||||
} else if (command == "refresh_plugins") {
|
||||
refresh_plugins();
|
||||
@@ -498,8 +507,8 @@ void PluginsDialog::on_script_message(const nlohmann::json& payload)
|
||||
install_plugin_from_file();
|
||||
} else if (command == "plugin_menu_action") {
|
||||
handle_plugin_menu_action(payload.value("plugin_key", ""), payload.value("action", ""));
|
||||
} else if (command == "run_script_plugin") {
|
||||
run_script_plugin(payload.value("plugin_key", ""), payload.value("capability_name", ""));
|
||||
} else if (command == "run_script_plugin_capability") {
|
||||
run_script_plugin_capability(payload.value("plugin_key", ""), payload.value("capability_name", ""));
|
||||
} else if (command == "open_terminal") {
|
||||
m_open_terminal_dlg_fn();
|
||||
} else if (command == "update_plugin") {
|
||||
@@ -575,16 +584,16 @@ bool PluginsDialog::get_descriptor(const std::string& plugin_key, PluginDescript
|
||||
return manager.try_get_plugin_descriptor(plugin_key, descriptor) && descriptor.is_invalid_package();
|
||||
}
|
||||
|
||||
void PluginsDialog::refresh_plugin_catalog_async(const wxString& title, const wxString& message, bool fetch_cloud)
|
||||
void PluginsDialog::refresh_plugin_metadata_async(const wxString& title, const wxString& message, bool fetch_cloud)
|
||||
{
|
||||
run_with_dialog([fetch_cloud]() { refresh_plugin_catalog_blocking(fetch_cloud); }, [this]() { send_plugins(); }, title, message);
|
||||
run_with_dialog([fetch_cloud]() { refresh_plugin_metadata_blocking(fetch_cloud); }, [this]() { send_plugins(); }, title, message);
|
||||
}
|
||||
|
||||
void PluginsDialog::refresh_plugins()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "Refreshing plugins from Plugins dialog";
|
||||
|
||||
refresh_plugin_catalog_async(_L("Refreshing"), _L("Refreshing plugins data"), kFetchCloudCatalog);
|
||||
refresh_plugin_metadata_async(_L("Refreshing"), _L("Refreshing plugins data"), kFetchCloudMeta);
|
||||
}
|
||||
|
||||
void PluginsDialog::toggle_plugin(const std::string& plugin_key, bool enabled)
|
||||
@@ -596,7 +605,6 @@ void PluginsDialog::toggle_plugin(const std::string& plugin_key, bool enabled)
|
||||
|
||||
PluginDescriptor row_data;
|
||||
if (!get_descriptor(plugin_key, row_data)) {
|
||||
// The catalog changed under the UI. Toggling is local, so just re-render from it.
|
||||
send_plugins();
|
||||
return;
|
||||
}
|
||||
@@ -688,7 +696,6 @@ void PluginsDialog::toggle_plugin_capability(const std::string& plugin_key,
|
||||
|
||||
PluginDescriptor row_data;
|
||||
if (!get_descriptor(plugin_key, row_data)) {
|
||||
// The catalog changed under the UI. Toggling is local, so just re-render from it.
|
||||
send_plugins();
|
||||
return;
|
||||
}
|
||||
@@ -741,12 +748,24 @@ void PluginsDialog::handle_plugin_menu_action(const std::string& plugin_key, con
|
||||
}
|
||||
}
|
||||
|
||||
void PluginsDialog::restore_z_order()
|
||||
{
|
||||
// Deferred so it runs on a clean stack after the modal has fully torn down; the
|
||||
// alive guard covers the dialog being destroyed while the CallAfter is queued.
|
||||
wxGetApp().CallAfter([this, alive = m_alive]() {
|
||||
if (alive->load(std::memory_order_acquire) && IsShown())
|
||||
Raise();
|
||||
});
|
||||
}
|
||||
|
||||
void PluginsDialog::install_plugin_from_file()
|
||||
{
|
||||
wxFileDialog dialog(this, _L("Select plugin package"), wxEmptyString, wxEmptyString, _L("Plugin files (*.py;*.whl)|*.py;*.whl"),
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
|
||||
if (dialog.ShowModal() != wxID_OK)
|
||||
const int rc = dialog.ShowModal();
|
||||
restore_z_order();
|
||||
if (rc != wxID_OK)
|
||||
return;
|
||||
|
||||
if (!install_plugin_package(dialog.GetPath().ToUTF8().data())) {
|
||||
@@ -799,7 +818,9 @@ bool PluginsDialog::install_plugin_package(const std::string& package_path)
|
||||
plugin_name),
|
||||
kOverwritePluginTitle, wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxICON_WARNING);
|
||||
dialog.SetOKCancelLabels(_L("Overwrite"), _L("Cancel"));
|
||||
if (dialog.ShowModal() != wxID_OK) {
|
||||
const int overwrite_rc = dialog.ShowModal();
|
||||
restore_z_order();
|
||||
if (overwrite_rc != wxID_OK) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Plugin package installation cancelled before overwrite. package=" << package_path
|
||||
<< " plugin=" << plugin_descriptor.name;
|
||||
return false;
|
||||
@@ -827,7 +848,7 @@ bool PluginsDialog::install_plugin_package(const std::string& package_path)
|
||||
BOOST_LOG_TRIVIAL(info) << "Plugin package installed successfully from " << package_path;
|
||||
const wxString installed_name = from_u8(plugin_descriptor.name.empty() ? package_file.filename().string() : plugin_descriptor.name);
|
||||
show_status(wxString::Format(_L("Installed \"%s\"."), installed_name), "success");
|
||||
refresh_plugin_catalog_async(_L("Refreshing"), _L("Refreshing plugins data"), kUseCurrentCloudCatalog);
|
||||
refresh_plugin_metadata_async(_L("Refreshing"), _L("Refreshing plugins data"), kUseCurrentCloudMeta);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -910,7 +931,7 @@ void PluginsDialog::restore_capability_config(const PluginCapabilityId& id)
|
||||
show_status(_L("Default configuration restored."), "success");
|
||||
}
|
||||
|
||||
void PluginsDialog::run_script_plugin(const std::string& plugin_key, const std::string& capability_name)
|
||||
void PluginsDialog::run_script_plugin_capability(const std::string& plugin_key, const std::string& capability_name)
|
||||
{
|
||||
PluginManager& manager = PluginManager::instance();
|
||||
|
||||
@@ -1046,16 +1067,17 @@ void PluginsDialog::delete_local_plugin(const PluginDescriptor& plugin)
|
||||
const wxString plugin_name = from_u8(plugin.name);
|
||||
const int rc = wxMessageBox(wxString::Format(_L("Delete plugin \"%s\"?\n\nThis permanently removes the plugin folder."), plugin_name),
|
||||
kDeletePluginTitle, wxYES_NO | wxNO_DEFAULT | wxICON_WARNING, this);
|
||||
restore_z_order();
|
||||
if (rc != wxYES)
|
||||
return;
|
||||
|
||||
auto state = std::make_shared<PluginOperationState>();
|
||||
run_with_dialog(
|
||||
[plugin_key = plugin.plugin_key, refresh_catalog = plugin.is_cloud_plugin(), state]() {
|
||||
[plugin_key = plugin.plugin_key, should_refresh = plugin.is_cloud_plugin(), state]() {
|
||||
std::string error;
|
||||
const bool succeeded = PluginManager::instance().delete_plugin(plugin_key, error);
|
||||
if (succeeded && refresh_catalog)
|
||||
refresh_plugin_catalog_blocking(kFetchCloudCatalog);
|
||||
if (succeeded && should_refresh)
|
||||
refresh_plugin_metadata_blocking(kFetchCloudMeta);
|
||||
store_plugin_operation_result(state, succeeded, std::move(error));
|
||||
},
|
||||
[this, state, plugin_name]() {
|
||||
@@ -1078,6 +1100,7 @@ void PluginsDialog::unsubscribe_cloud_plugin(const PluginDescriptor& plugin)
|
||||
wxString::Format(_L("Unsubscribe plugin \"%s\"?\n\nThis will stop tracking the plugin and delete any local plugin files."),
|
||||
plugin_name),
|
||||
kUnsubscribeTitle, wxYES_NO | wxNO_DEFAULT | wxICON_WARNING, this);
|
||||
restore_z_order();
|
||||
if (rc != wxYES)
|
||||
return;
|
||||
|
||||
@@ -1159,7 +1182,7 @@ void PluginsDialog::reinstall_cloud_plugin(const PluginDescriptor& plugin)
|
||||
return;
|
||||
}
|
||||
|
||||
manager.update_cloud_catalog(std::vector<PluginDescriptor>{as_cloud_only_descriptor(plugin)});
|
||||
manager.update_cloud_metadata(std::vector<PluginDescriptor>{as_cloud_only_descriptor(plugin)});
|
||||
}
|
||||
|
||||
if (!install_cloud_plugin(plugin_key, plugin.version, from_u8(plugin.name))) {
|
||||
@@ -1207,6 +1230,7 @@ void PluginsDialog::delete_mine_local_and_cloud_plugin(const std::string& plugin
|
||||
"deletes the plugin from the cloud. This action cannot be undone."),
|
||||
plugin_name),
|
||||
kDeletePluginTitle, wxYES_NO | wxNO_DEFAULT | wxICON_WARNING, this);
|
||||
restore_z_order();
|
||||
if (rc != wxYES)
|
||||
return;
|
||||
|
||||
@@ -1216,8 +1240,6 @@ void PluginsDialog::delete_mine_local_and_cloud_plugin(const std::string& plugin
|
||||
return;
|
||||
}
|
||||
|
||||
// delete_mine_local_and_cloud_plugin already updated the in-memory catalog (see
|
||||
// finalize_cloud_plugin_removal), so a UI refresh is sufficient here.
|
||||
send_plugins();
|
||||
show_status(wxString::Format(_L("Deleted \"%s\"."), plugin_name), "success");
|
||||
}
|
||||
|
||||
@@ -53,6 +53,13 @@ private:
|
||||
void open_plugin_on_cloud(const std::string& sharing_token);
|
||||
void open_plugin_hub();
|
||||
void on_script_message(const nlohmann::json& payload) override;
|
||||
// Runs one web command on a clean main-loop stack; see on_script_message.
|
||||
void handle_web_command(const nlohmann::json& payload);
|
||||
// Re-raises this dialog after a transient modal it opened (file dialog, message box,
|
||||
// progress dialog). Native macOS panels end by re-activating the app's main window
|
||||
// (the mainframe) instead of this webview-hosting dialog, burying it; wx only
|
||||
// compensates for generic wxDialog modals (wxDialog::EndModal raises the parent).
|
||||
void restore_z_order();
|
||||
|
||||
void send_plugins();
|
||||
void set_plugin_sort(const std::string& sort_key, const std::string& sort_order);
|
||||
@@ -60,7 +67,7 @@ private:
|
||||
|
||||
bool get_descriptor(const std::string& plugin_key, Slic3r::PluginDescriptor& descriptor) const;
|
||||
|
||||
void refresh_plugin_catalog_async(const wxString& title, const wxString& message, bool fetch_cloud);
|
||||
void refresh_plugin_metadata_async(const wxString& title, const wxString& message, bool fetch_cloud);
|
||||
void refresh_plugins();
|
||||
void toggle_plugin(const std::string& plugin_key, bool enabled);
|
||||
void toggle_plugin_capability(const std::string& plugin_key, PluginCapabilityType type, const std::string& capability_name, bool enabled);
|
||||
@@ -69,7 +76,7 @@ private:
|
||||
void install_plugin_from_file();
|
||||
bool install_plugin_package(const std::string& package_path);
|
||||
bool install_cloud_plugin(const std::string& uuid, const std::string& version, const wxString& name);
|
||||
void run_script_plugin(const std::string& plugin_key, const std::string& capability_name);
|
||||
void run_script_plugin_capability(const std::string& plugin_key, const std::string& capability_name);
|
||||
// Config tab. Both are scoped to the full capability ID: a request naming a
|
||||
// capability that is gone or not configurable is refused rather than served from, or written
|
||||
// to, some other entry.
|
||||
@@ -114,7 +121,8 @@ private:
|
||||
|
||||
timer->Start(100);
|
||||
|
||||
std::thread([alive,
|
||||
std::thread([this,
|
||||
alive,
|
||||
progress,
|
||||
timer,
|
||||
run = std::forward<Run>(run),
|
||||
@@ -131,7 +139,8 @@ private:
|
||||
if (wxTheApp == nullptr)
|
||||
return;
|
||||
|
||||
wxTheApp->CallAfter([alive,
|
||||
wxTheApp->CallAfter([this,
|
||||
alive,
|
||||
progress,
|
||||
timer,
|
||||
on_finish = std::move(on_finish),
|
||||
@@ -141,6 +150,7 @@ private:
|
||||
|
||||
if (alive->load(std::memory_order_acquire)) {
|
||||
progress->Destroy();
|
||||
restore_z_order();
|
||||
on_finish();
|
||||
} else if (finish_after_dialog_destroyed) {
|
||||
on_finish();
|
||||
@@ -240,9 +250,9 @@ private:
|
||||
PluginSortKey m_plugin_sort_key = PluginSortKey::None;
|
||||
PluginSortOrder m_plugin_sort_order = PluginSortOrder::Asc;
|
||||
|
||||
// Serializes run_script_plugin. With main-thread execution a plugin's orca.host.ui modal
|
||||
// Serializes run_script_plugin_capability. With main-thread execution a plugin's orca.host.ui modal
|
||||
// (message/show_dialog) or the result message box pumps a nested event loop, which could
|
||||
// re-dispatch the web "run_script_plugin" command and start a second, overlapping run.
|
||||
// re-dispatch the web "run_script_plugin_capability" command and start a second, overlapping run.
|
||||
bool m_script_running = false;
|
||||
|
||||
// Plugin whose asynchronous activation is in flight, awaited by resolve_pending_activation().
|
||||
|
||||
@@ -521,6 +521,14 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
|
||||
//m_change_filament_times_sizer->Add(m_img_change_filament_times, 0, wxTOP, FromDIP(2));
|
||||
m_change_filament_times_sizer->Add(m_txt_change_filament_times, 0, wxTOP, 0);
|
||||
|
||||
m_warn_when_drying_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_txt_warn_when_drying = new Label(m_scroll_area, wxEmptyString);
|
||||
m_txt_warn_when_drying->SetFont(::Label::Body_13);
|
||||
m_txt_warn_when_drying->SetForegroundColour(wxColour("#F09A17"));
|
||||
m_txt_warn_when_drying->SetBackgroundColour(*wxWHITE);
|
||||
m_txt_warn_when_drying->SetLabel(_L("To ensure print quality, the drying temperature will be lowered during printing."));
|
||||
m_warn_when_drying_sizer->Add(m_txt_warn_when_drying, 0, wxTOP, FromDIP(2));
|
||||
|
||||
/*Advanced Options*/
|
||||
wxBoxSizer* sizer_split_options = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto m_split_options_line = new wxPanel(m_scroll_area, wxID_ANY);
|
||||
@@ -735,6 +743,8 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
|
||||
m_scroll_sizer->Add(m_change_filament_times_sizer, 0,wxLEFT|wxRIGHT, FromDIP(15));
|
||||
// m_scroll_sizer->Add(m_link_edit_nozzle, 0, wxLEFT|wxRIGHT, FromDIP(15));
|
||||
m_scroll_sizer->Add(suggestion_sizer, 0, wxLEFT|wxRIGHT|wxEXPAND, FromDIP(15));
|
||||
m_scroll_sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
m_scroll_sizer->Add(m_warn_when_drying_sizer, 0, wxLEFT|wxRIGHT, FromDIP(15));
|
||||
m_scroll_sizer->Add(sizer_split_options, 1, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(15));
|
||||
m_scroll_sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
m_scroll_sizer->Add(m_options_other, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(15));
|
||||
@@ -1734,6 +1744,47 @@ bool SelectMachineDialog::CheckErrorSyncNozzleMappingResultV0(MachineObject* obj
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SelectMachineDialog::is_ams_drying(MachineObject* obj)
|
||||
{
|
||||
const auto& ams_list = obj->GetFilaSystem()->GetAmsList();
|
||||
for (auto ams = ams_list.begin(); ams != ams_list.end(); ams++) {
|
||||
if (ams->second->AmsIsDrying()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SelectMachineDialog::is_selected_ams_drying(MachineObject* obj)
|
||||
{
|
||||
if (!obj) return false;
|
||||
|
||||
// If a UI material is selected, only when that material is mapped to an AMS
|
||||
// and that AMS is currently drying.
|
||||
for (const auto &kv : m_materialList) {
|
||||
Material *mat = kv.second;
|
||||
if (!mat || !mat->item) continue;
|
||||
if (!mat->item->m_selected) continue;
|
||||
|
||||
// find mapping entry for this material id
|
||||
for (const FilamentInfo &f : m_ams_mapping_result) {
|
||||
if (f.id != mat->id) continue;
|
||||
|
||||
if (f.ams_id.empty()) return false;
|
||||
|
||||
auto fila_system = obj->GetFilaSystem();
|
||||
if (!fila_system) return false;
|
||||
DevAms* dev_ams = fila_system->GetAmsById(f.ams_id);
|
||||
return (dev_ams && dev_ams->AmsIsDrying());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SelectMachineDialog::prepare(int print_plate_idx)
|
||||
{
|
||||
m_print_plate_idx = print_plate_idx;
|
||||
@@ -3888,6 +3939,16 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_)
|
||||
m_check_ext_change_assist->Enable(false);
|
||||
}
|
||||
|
||||
{
|
||||
const bool show_warn_when_drying = is_selected_ams_drying(obj_);
|
||||
const bool is_currently_shown = (m_txt_warn_when_drying != nullptr) ? m_txt_warn_when_drying->IsShown() : false;
|
||||
if (is_currently_shown != show_warn_when_drying) {
|
||||
m_warn_when_drying_sizer->Show(show_warn_when_drying);
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
}
|
||||
|
||||
/*reading done*/
|
||||
if (wxGetApp().app_config) {
|
||||
if (obj_->upgrade_force_upgrade) {
|
||||
@@ -4404,6 +4465,7 @@ void SelectMachineDialog::set_default()
|
||||
m_mapping_sugs_sizer->Show(false);
|
||||
m_change_filament_times_sizer->Show(false);
|
||||
m_txt_change_filament_times->Show(false);
|
||||
m_warn_when_drying_sizer->Show(false);
|
||||
|
||||
// rset status bar
|
||||
m_status_bar->reset();
|
||||
@@ -4513,6 +4575,10 @@ void SelectMachineDialog::reset_and_sync_ams_list()
|
||||
m_filaments_map = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_real_filament_maps(project_config);
|
||||
}
|
||||
|
||||
bool selected_any = false;
|
||||
MaterialItem *first_enabled = nullptr;
|
||||
int first_enabled_id = -1;
|
||||
|
||||
for (auto i = 0; i < extruders.size(); i++) {
|
||||
auto extruder = extruders[i] - 1;
|
||||
auto colour = wxGetApp().preset_bundle->project_config.opt_string("filament_colour", (unsigned int) extruder);
|
||||
@@ -4542,7 +4608,20 @@ void SelectMachineDialog::reset_and_sync_ams_list()
|
||||
item = new MaterialItem(m_filament_panel, colour_rgb, _L(display_materials[extruder]));
|
||||
m_sizer_ams_mapping->Add(item, 0, wxALL, FromDIP(5));
|
||||
}
|
||||
|
||||
if (!item) continue;
|
||||
|
||||
item->SetToolTip(m_ams_tooltip);
|
||||
|
||||
if (!selected_any && extruder == m_current_filament_id && item->m_enable) {
|
||||
item->on_selected();
|
||||
selected_any = true;
|
||||
}
|
||||
if (!first_enabled && item->m_enable) {
|
||||
first_enabled = item;
|
||||
first_enabled_id = extruder;
|
||||
}
|
||||
|
||||
item->Bind(wxEVT_LEFT_UP, [this, item, materials, extruder](wxMouseEvent &e) {});
|
||||
item->Bind(wxEVT_LEFT_DOWN, [this, item, materials, extruder](wxMouseEvent &e) {
|
||||
if (!item->m_enable) {return;}
|
||||
@@ -4621,6 +4700,11 @@ void SelectMachineDialog::reset_and_sync_ams_list()
|
||||
}
|
||||
}
|
||||
|
||||
if (!selected_any && first_enabled) {
|
||||
m_current_filament_id = first_enabled_id;
|
||||
first_enabled->on_selected();
|
||||
}
|
||||
|
||||
if (use_double_extruder)
|
||||
{
|
||||
m_filament_left_panel->Show();
|
||||
@@ -5031,6 +5115,10 @@ void SelectMachineDialog::set_default_from_sdcard()
|
||||
m_materialList.clear();
|
||||
m_filaments.clear();
|
||||
|
||||
bool selected_any = false;
|
||||
MaterialItem *first_enabled = nullptr;
|
||||
int first_enabled_id = -1;
|
||||
|
||||
for (auto i = 0; i < m_required_data_plate_data_list[m_print_plate_idx]->slice_filaments_info.size(); i++) {
|
||||
FilamentInfo fo = m_required_data_plate_data_list[m_print_plate_idx]->slice_filaments_info[i];
|
||||
|
||||
@@ -5053,6 +5141,17 @@ void SelectMachineDialog::set_default_from_sdcard()
|
||||
m_sizer_ams_mapping->Add(item, 0, wxALL, FromDIP(5));
|
||||
}
|
||||
|
||||
if (!item) continue;
|
||||
|
||||
if (!selected_any && fo.id == m_current_filament_id && item->m_enable) {
|
||||
item->on_selected();
|
||||
selected_any = true;
|
||||
}
|
||||
if (!first_enabled && item->m_enable) {
|
||||
first_enabled = item;
|
||||
first_enabled_id = fo.id;
|
||||
}
|
||||
|
||||
item->Bind(wxEVT_LEFT_UP, [this, item, materials](wxMouseEvent& e) {});
|
||||
item->Bind(wxEVT_LEFT_DOWN, [this, obj_, item, materials, diameters_count, fo](wxMouseEvent& e) {
|
||||
if (!item->m_enable) {return;}
|
||||
@@ -5129,6 +5228,11 @@ void SelectMachineDialog::set_default_from_sdcard()
|
||||
wxSize screenSize = wxGetDisplaySize();
|
||||
auto dialogSize = this->GetSize();
|
||||
|
||||
if (!selected_any && first_enabled) {
|
||||
m_current_filament_id = first_enabled_id;
|
||||
first_enabled->on_selected();
|
||||
}
|
||||
|
||||
reset_ams_material();
|
||||
|
||||
// basic info
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "boost/bimap/bimap.hpp"
|
||||
#include "AmsMappingPopup.hpp"
|
||||
#include "GUI_ObjectLayers.hpp"
|
||||
#include "ReleaseNote.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
@@ -354,6 +355,7 @@ protected:
|
||||
wxBoxSizer* m_sizer_autorefill{ nullptr };
|
||||
wxBoxSizer* m_mapping_sugs_sizer{ nullptr };
|
||||
wxBoxSizer* m_change_filament_times_sizer{ nullptr };
|
||||
wxBoxSizer* m_warn_when_drying_sizer{ nullptr };
|
||||
Button* m_button_ensure{ nullptr };
|
||||
wxStaticBitmap * m_rename_button{nullptr};
|
||||
wxStaticBitmap* m_staticbitmap{ nullptr };
|
||||
@@ -387,6 +389,8 @@ protected:
|
||||
CheckBox* m_check_ext_change_assist{ nullptr };
|
||||
Label* m_label_ext_change_assist{ nullptr };
|
||||
|
||||
Label* m_txt_warn_when_drying{ nullptr };
|
||||
|
||||
PrinterInfoBox* m_printer_box { nullptr};
|
||||
PrinterMsgPanel * m_text_printer_msg{nullptr};
|
||||
Label* m_text_printer_msg_tips{ nullptr };
|
||||
@@ -542,6 +546,9 @@ public:
|
||||
bool CheckErrorDynamicSwitchNozzle(MachineObject* obj_);
|
||||
void on_flow_cali_option_changed();
|
||||
|
||||
bool is_ams_drying(MachineObject* obj);
|
||||
bool is_selected_ams_drying(MachineObject* obj);
|
||||
|
||||
PrintFromType get_print_type() {return m_print_type;};
|
||||
wxString format_steel_name(NozzleType type);
|
||||
PrintDialogStatus get_status() { return m_print_status; }
|
||||
|
||||
@@ -3392,6 +3392,7 @@ void StatusPanel::update_ams(MachineObject *obj)
|
||||
|
||||
// must select a current can
|
||||
m_ams_control->UpdateAms(obj->get_printer_series_str(), obj->printer_type, ams_info, ext_info, *obj->GetExtderSystem(), obj->get_dev_id(), false);
|
||||
m_ams_control->UpdateAmsDryControl(obj);
|
||||
|
||||
last_tray_exist_bits = obj->tray_exist_bits;
|
||||
last_ams_exist_bits = obj->ams_exist_bits;
|
||||
|
||||
@@ -7917,7 +7917,7 @@ bool Tab::validate_filament_temperature_pairs()
|
||||
if (delta <= rule.max_delta)
|
||||
continue;
|
||||
|
||||
const wxString deg_c = wxString::FromUTF8("°C");
|
||||
const wxString deg_c = wxString::FromUTF8("℃");
|
||||
const wxString bullet = wxString::FromUTF8("•");
|
||||
invalid_pairs += wxString::Format(_L(" - %s:\n %s first layer %d %s, other layers %d %s\n %s max delta %d %s, current delta %d %s\n"),
|
||||
rule.label, bullet, first_temp, deg_c, other_temp, deg_c, bullet, rule.max_delta, deg_c, delta, deg_c);
|
||||
|
||||
@@ -31,6 +31,7 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons
|
||||
, m_Humidity_tip_popup(AmsHumidityTipPopup(this))
|
||||
, m_percent_humidity_dry_popup(new uiAmsPercentHumidityDryPopup(this))
|
||||
, m_ams_introduce_popup(AmsIntroducePopup(this))
|
||||
, m_ams_dry_ctr_win(new AMSDryCtrWin(this))
|
||||
{
|
||||
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (dev) {
|
||||
@@ -252,6 +253,12 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons
|
||||
uiAmsHumidityInfo *info = (uiAmsHumidityInfo *) evt.GetClientData();
|
||||
if (info)
|
||||
{
|
||||
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
MachineObject *obj = nullptr;
|
||||
if (dev) {
|
||||
obj = dev->get_selected_machine();
|
||||
}
|
||||
|
||||
if (info->ams_type == AMSModel::GENERIC_AMS)
|
||||
{
|
||||
wxPoint img_pos = ClientToScreen(wxPoint(0, 0));
|
||||
@@ -261,9 +268,14 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons
|
||||
int humidity_value = info->humidity_display_idx;
|
||||
if (humidity_value > 0 && humidity_value <= 5) { m_Humidity_tip_popup.set_humidity_level(humidity_value); }
|
||||
m_Humidity_tip_popup.Popup();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else if (obj && obj->is_support_remote_dry && (info->ams_type == AMSModel::N3F_AMS || info->ams_type == AMSModel::N3S_AMS)){
|
||||
m_ams_dry_ctr_win->set_ams_id(info->ams_id);
|
||||
|
||||
wxPoint img_pos = ClientToScreen(wxPoint(0, 0));
|
||||
wxPoint popup_pos(img_pos.x - m_ams_dry_ctr_win->GetSize().GetWidth() + FromDIP(150), img_pos.y - FromDIP(80));
|
||||
m_ams_dry_ctr_win->Move(popup_pos);
|
||||
m_ams_dry_ctr_win->ShowModal();
|
||||
} else {
|
||||
m_percent_humidity_dry_popup->Update(info);
|
||||
|
||||
wxPoint img_pos = ClientToScreen(wxPoint(0, 0));
|
||||
@@ -283,7 +295,12 @@ void AMSControl::on_retry()
|
||||
post_event(wxCommandEvent(EVT_AMS_RETRY));
|
||||
}
|
||||
|
||||
AMSControl::~AMSControl() {}
|
||||
AMSControl::~AMSControl()
|
||||
{
|
||||
if (m_ams_dry_ctr_win) {
|
||||
delete m_ams_dry_ctr_win;
|
||||
}
|
||||
}
|
||||
|
||||
std::string AMSControl::GetCurentAms() {
|
||||
return m_current_ams;
|
||||
@@ -501,6 +518,10 @@ void AMSControl::msw_rescale()
|
||||
m_percent_humidity_dry_popup->msw_rescale();
|
||||
}
|
||||
|
||||
if (m_ams_dry_ctr_win) {
|
||||
m_ams_dry_ctr_win->msw_rescale();
|
||||
}
|
||||
|
||||
m_Humidity_tip_popup.msw_rescale();
|
||||
|
||||
Layout();
|
||||
@@ -824,6 +845,27 @@ void AMSControl::show_vams_kn_value(bool show)
|
||||
//m_vams_lib->show_kn_value(show);
|
||||
}
|
||||
|
||||
void AMSControl::UpdateAmsDryControl(MachineObject* obj)
|
||||
{
|
||||
if (!m_ams_dry_ctr_win->IsShown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj || !obj->GetFilaSystem()) {
|
||||
m_ams_dry_ctr_win->Close();
|
||||
return;
|
||||
}
|
||||
|
||||
std::weak_ptr<DevFilaSystem> weak_fila_system = obj->GetFilaSystem();
|
||||
|
||||
if (auto locaked_fila_system = weak_fila_system.lock()) {
|
||||
m_ams_dry_ctr_win->update(locaked_fila_system, obj);
|
||||
} else {
|
||||
m_ams_dry_ctr_win->Close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<AMSinfo> AMSControl::GenerateSimulateData() {
|
||||
auto caninfo0_0 = Caninfo{ "0", (""), *wxRED, AMSCanType::AMS_CAN_TYPE_VIRTUAL };
|
||||
auto caninfo0_1 = Caninfo{ "1", (""), *wxGREEN, AMSCanType::AMS_CAN_TYPE_VIRTUAL };
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <tuple>
|
||||
|
||||
#include "slic3r/GUI/DeviceCore/DevExtruderSystem.h"
|
||||
#include "slic3r/GUI/AMSDryControl.hpp"
|
||||
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
@@ -127,6 +128,7 @@ protected:
|
||||
|
||||
AmsHumidityTipPopup m_Humidity_tip_popup;
|
||||
uiAmsPercentHumidityDryPopup* m_percent_humidity_dry_popup;
|
||||
AMSDryCtrWin* m_ams_dry_ctr_win;
|
||||
|
||||
std::string m_last_ams_id = "";
|
||||
std::string m_last_tray_id = "";
|
||||
@@ -170,6 +172,7 @@ public:
|
||||
void CreateAmsDoubleNozzle(const std::string &series_name, const std::string& printer_type);
|
||||
void CreateAmsSingleNozzle(const std::string &series_name, const std::string &printer_type);
|
||||
void ClearAms();
|
||||
void UpdateAmsDryControl(MachineObject* obj);
|
||||
void UpdateAms(const std::string &series_name,
|
||||
const std::string &printer_type,
|
||||
std::vector<AMSinfo> ams_info,
|
||||
|
||||
Reference in New Issue
Block a user