Merge branch 'main' into dev/h2d-2
# Conflicts: # localization/i18n/list.txt # src/slic3r/GUI/CalibrationWizardPresetPage.cpp # src/slic3r/GUI/DeviceManager.cpp # src/slic3r/GUI/DeviceManager.hpp # src/slic3r/GUI/Printer/PrinterFileSystem.cpp # src/slic3r/GUI/Printer/PrinterFileSystem.h # src/slic3r/GUI/SelectMachine.hpp # src/slic3r/GUI/SendToPrinter.cpp # src/slic3r/GUI/SendToPrinter.hpp # src/slic3r/GUI/StatusPanel.hpp # src/slic3r/GUI/Widgets/AnimaController.cpp
This commit is contained in:
@@ -5415,9 +5415,9 @@ void PrintConfigDef::init_fff_params()
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("support_remove_small_overhang", coBool);
|
||||
def->label = L("Remove small overhangs");
|
||||
def->label = L("Ignore small overhangs");
|
||||
def->category = L("Support");
|
||||
def->tooltip = L("Remove small overhangs that possibly need no supports.");
|
||||
def->tooltip = L("Ignore small overhangs that possibly don't require support.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
|
||||
@@ -405,6 +405,11 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/SavePresetDialog.hpp
|
||||
GUI/SceneRaycaster.cpp
|
||||
GUI/SceneRaycaster.hpp
|
||||
GUI/PartSkipCommon.hpp
|
||||
GUI/PartSkipDialog.cpp
|
||||
GUI/PartSkipDialog.hpp
|
||||
GUI/SkipPartCanvas.cpp
|
||||
GUI/SkipPartCanvas.hpp
|
||||
GUI/Search.cpp
|
||||
GUI/Search.hpp
|
||||
GUI/Selection.cpp
|
||||
|
||||
@@ -1336,6 +1336,17 @@ int MachineObject::command_go_home()
|
||||
return this->is_in_printing() ? this->publish_gcode("G28 X\n") : this->publish_gcode("G28 \n");
|
||||
}
|
||||
|
||||
int MachineObject::command_task_partskip(std::vector<int> part_ids)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(trace) << "command_task_partskip: ";
|
||||
json j;
|
||||
j["print"]["command"] = "skip_objects";
|
||||
j["print"]["obj_list"] = part_ids;
|
||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
|
||||
return this->publish_json(j, 1);
|
||||
}
|
||||
|
||||
int MachineObject::command_task_abort()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(trace) << "command_task_abort: ";
|
||||
@@ -2313,6 +2324,7 @@ void MachineObject::reset()
|
||||
}
|
||||
}
|
||||
subtask_ = nullptr;
|
||||
m_partskip_ids.clear();
|
||||
}
|
||||
|
||||
void MachineObject::set_print_state(std::string status)
|
||||
@@ -2567,6 +2579,29 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
||||
|
||||
print_json.diff2all_base_reset(j_pre);
|
||||
}
|
||||
|
||||
if (j_pre["print"].contains("s_obj")){
|
||||
if(j_pre["print"]["s_obj"].is_array()){
|
||||
m_partskip_ids.clear();
|
||||
for(auto it=j_pre["print"]["s_obj"].begin(); it!=j_pre["print"]["s_obj"].end(); it++){
|
||||
m_partskip_ids.push_back(it.value().get<int>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j_pre["print"].contains("plate_idx")){ // && m_plate_index == -1
|
||||
if (j_pre["print"]["plate_idx"].is_number())
|
||||
{
|
||||
m_plate_index = j_pre["print"]["plate_idx"].get<int>();
|
||||
}
|
||||
else if (j_pre["print"]["plate_idx"].is_string())
|
||||
{
|
||||
try
|
||||
{
|
||||
m_plate_index = std::stoi(j_pre["print"]["plate_idx"].get<std::string>());
|
||||
}
|
||||
catch (...) { BOOST_LOG_TRIVIAL(error) << "parse_json: failed to convert plate_idx to int"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4407,6 +4442,7 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil
|
||||
|
||||
if (plate_idx >= 0) {
|
||||
plate_index = plate_idx;
|
||||
this->m_plate_index = plate_idx;
|
||||
}
|
||||
else {
|
||||
std::string subtask_json;
|
||||
@@ -4469,8 +4505,7 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil
|
||||
BOOST_LOG_TRIVIAL(error) << "task_info: get subtask id failed!";
|
||||
}
|
||||
}
|
||||
|
||||
this->m_plate_index = plate_index;
|
||||
// this->m_plate_index = plate_index;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4880,6 +4915,7 @@ void MachineObject::parse_new_info(json print)
|
||||
is_support_airprinting_detection = get_flag_bits(fun, 45);
|
||||
m_fan->SetSupportCoolingFilter(get_flag_bits(fun, 46));
|
||||
is_support_ext_change_assist = get_flag_bits(fun, 48);
|
||||
is_support_partskip = get_flag_bits(fun, 49);
|
||||
}
|
||||
|
||||
/*aux*/
|
||||
|
||||
@@ -554,6 +554,9 @@ public:
|
||||
time_t xcam_prompt_sound_hold_start = 0;
|
||||
time_t xcam_filament_tangle_detect_hold_start = 0;
|
||||
|
||||
// part skip
|
||||
std::vector<int> m_partskip_ids;
|
||||
|
||||
/*target from Studio-SwitchBoard, default to INVALID_NOZZLE_ID if no switching control from PC*/
|
||||
int targ_nozzle_id_from_pc = INVALID_EXTRUDER_ID;
|
||||
|
||||
@@ -593,6 +596,7 @@ public:
|
||||
bool m_support_mqtt_homing { false };// fun[32]
|
||||
bool is_support_brtc{false}; // fun[31], support tcp and upload protocol
|
||||
bool is_support_ext_change_assist{false};
|
||||
bool is_support_partskip{false};
|
||||
|
||||
// refine printer function options
|
||||
bool is_support_spaghetti_detection{false};
|
||||
@@ -689,6 +693,7 @@ public:
|
||||
|
||||
int command_task_abort();
|
||||
/* cancelled the job_id */
|
||||
int command_task_partskip(std::vector<int> part_ids);
|
||||
int command_task_cancel(std::string job_id);
|
||||
int command_task_pause();
|
||||
int command_task_resume();
|
||||
|
||||
18
src/slic3r/GUI/PartSkipCommon.hpp
Normal file
18
src/slic3r/GUI/PartSkipCommon.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef PARTSKIPCOMMON_H
|
||||
#define PARTSKIPCOMMON_H
|
||||
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
enum PartState {
|
||||
psUnCheck,
|
||||
psChecked,
|
||||
psSkipped
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<std::pair<int, PartState>> PartsInfo;
|
||||
|
||||
}}
|
||||
|
||||
#endif // PARTSKIPCOMMON_H
|
||||
1049
src/slic3r/GUI/PartSkipDialog.cpp
Normal file
1049
src/slic3r/GUI/PartSkipDialog.cpp
Normal file
File diff suppressed because it is too large
Load Diff
163
src/slic3r/GUI/PartSkipDialog.hpp
Normal file
163
src/slic3r/GUI/PartSkipDialog.hpp
Normal file
@@ -0,0 +1,163 @@
|
||||
#include <wx/panel.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/webrequest.h>
|
||||
#include <wx/control.h>
|
||||
#include <wx/dcclient.h>
|
||||
#include <wx/display.h>
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/sstream.h>
|
||||
#include <wx/zstream.h>
|
||||
#include <wx/window.h>
|
||||
#include <wx/dcgraph.h>
|
||||
#include <wx/simplebook.h>
|
||||
|
||||
#include "Widgets/Label.hpp"
|
||||
#include "Widgets/CheckBox.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "Widgets/AnimaController.hpp"
|
||||
#include "DeviceManager.hpp"
|
||||
#include "PartSkipCommon.hpp"
|
||||
#include "Printer/PrinterFileSystem.h"
|
||||
#include "I18N.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
class SkipPartCanvas;
|
||||
|
||||
enum URL_STATE {
|
||||
URL_TCP,
|
||||
URL_TUTK,
|
||||
};
|
||||
|
||||
class PartSkipConfirmDialog : public DPIDialog
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
Label *m_msg_label;
|
||||
Label *m_tip_label;
|
||||
Button *m_apply_button;
|
||||
|
||||
public:
|
||||
PartSkipConfirmDialog(wxWindow *parent);
|
||||
~PartSkipConfirmDialog();
|
||||
|
||||
void on_dpi_changed(const wxRect &suggested_rect);
|
||||
Button *GetConfirmButton();
|
||||
void SetMsgLabel(wxString msg);
|
||||
void SetTipLabel(wxString msg);
|
||||
bool Show(bool show);
|
||||
};
|
||||
|
||||
class PartSkipDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
PartSkipDialog(wxWindow *parent);
|
||||
~PartSkipDialog();
|
||||
void on_dpi_changed(const wxRect &suggested_rect);
|
||||
bool Show(bool show);
|
||||
|
||||
void UpdatePartsStateFromPrinter(MachineObject *obj_);
|
||||
void SetSimplebookPage(int page);
|
||||
void InitSchedule(MachineObject *obj_);
|
||||
void InitDialogUI();
|
||||
int GetAllSkippedPartsNum();
|
||||
|
||||
MachineObject *m_obj{nullptr};
|
||||
|
||||
wxSimplebook *m_simplebook;
|
||||
wxPanel *m_book_third_panel;
|
||||
wxPanel *m_book_second_panel;
|
||||
wxPanel *m_book_first_panel;
|
||||
|
||||
SkipPartCanvas *m_canvas;
|
||||
Button *m_zoom_in_btn;
|
||||
Button *m_zoom_out_btn;
|
||||
Button *m_switch_drag_btn;
|
||||
CheckBox *m_all_checkbox;
|
||||
Button *m_percent_label;
|
||||
Label *m_all_label;
|
||||
wxPanel *m_line;
|
||||
wxPanel *m_line_top;
|
||||
wxScrolledWindow *m_list_view;
|
||||
|
||||
wxPanel *m_dlg_placeholder;
|
||||
Label *m_cnt_label;
|
||||
Label *m_tot_label;
|
||||
|
||||
Button *m_apply_btn;
|
||||
|
||||
Label *m_loading_label;
|
||||
Label *m_retry_label;
|
||||
ScalableBitmap *m_retry_icon;
|
||||
wxStaticBitmap *m_retry_bitmap;
|
||||
|
||||
wxBoxSizer *m_sizer;
|
||||
wxBoxSizer *m_dlg_sizer;
|
||||
wxBoxSizer *m_dlg_content_sizer;
|
||||
wxBoxSizer *m_dlg_btn_sizer;
|
||||
wxBoxSizer *m_canvas_sizer;
|
||||
wxBoxSizer *m_canvas_btn_sizer;
|
||||
wxBoxSizer *m_list_sizer;
|
||||
wxBoxSizer *m_scroll_sizer;
|
||||
wxBoxSizer *m_book_first_sizer;
|
||||
wxBoxSizer *m_book_second_sizer;
|
||||
wxBoxSizer *m_book_second_btn_sizer;
|
||||
Button *m_second_retry_btn;
|
||||
AnimaIcon *m_loading_icon;
|
||||
|
||||
private:
|
||||
int m_plate_idx{-1};
|
||||
int m_zoom_percent{100};
|
||||
bool m_is_drag{false};
|
||||
bool m_print_lock{true};
|
||||
bool m_enable_apply_btn{false};
|
||||
bool is_model_support_partskip{false};
|
||||
|
||||
std::map<uint32_t, PartState> m_parts_state;
|
||||
std::map<uint32_t, std::string> m_parts_name;
|
||||
std::vector<int> m_partskip_ids;
|
||||
|
||||
enum URL_STATE m_url_state = URL_STATE::URL_TCP;
|
||||
|
||||
PartsInfo GetPartsInfo();
|
||||
bool is_drag_mode();
|
||||
|
||||
boost::shared_ptr<PrinterFileSystem> m_file_sys;
|
||||
bool m_file_sys_result{false};
|
||||
std::string m_timestamp;
|
||||
std::string m_tmp_path;
|
||||
std::vector<string> m_local_paths;
|
||||
std::vector<string> m_target_paths;
|
||||
std::string create_tmp_path();
|
||||
|
||||
bool is_local_file_existed(const std::vector<string> &local_paths);
|
||||
|
||||
void DownloadPartsFile();
|
||||
void OnFileSystemEvent(wxCommandEvent &event);
|
||||
void OnFileSystemResult(wxCommandEvent &event);
|
||||
void fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs);
|
||||
|
||||
void OnZoomIn(wxCommandEvent &event);
|
||||
void OnZoomOut(wxCommandEvent &event);
|
||||
void OnSwitchDrag(wxCommandEvent &event);
|
||||
void OnZoomPercent(wxCommandEvent &event);
|
||||
void UpdatePartsStateFromCanvas(wxCommandEvent &event);
|
||||
|
||||
void UpdateZoomPercent();
|
||||
void UpdateCountLabel();
|
||||
void UpdateDialogUI();
|
||||
void UpdateApplyButtonStatus();
|
||||
bool IsAllChecked();
|
||||
bool IsAllCancled();
|
||||
|
||||
void OnRetryButton(wxCommandEvent &event);
|
||||
void OnAllCheckbox(wxCommandEvent &event);
|
||||
void OnApplyDialog(wxCommandEvent &event);
|
||||
};
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
@@ -39,6 +39,7 @@ wxDEFINE_EVENT(EVT_FILE_CHANGED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_SELECT_CHANGED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_THUMBNAIL, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_DOWNLOAD, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_RAMDOWNLOAD, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_MEDIA_ABILITY_CHANGED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_UPLOADING, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_UPLOAD_CHANGED, wxCommandEvent);
|
||||
@@ -271,6 +272,149 @@ struct PrinterFileSystem::Upload : Progress
|
||||
boost::filesystem::ifstream ifs;
|
||||
};
|
||||
|
||||
|
||||
void PrinterFileSystem::GetPickImages(const std::vector<std::string> &local_paths, const std::vector<std::string> &targetpaths)
|
||||
{
|
||||
m_download_states.clear();
|
||||
|
||||
GetPickImage(1, local_paths[0], targetpaths[0]);
|
||||
GetPickImage(2, local_paths[1], targetpaths[1]);
|
||||
GetPickImage(3, local_paths[2], targetpaths[2]);
|
||||
|
||||
}
|
||||
|
||||
void PrinterFileSystem::GetPickImage(int id, const std::string &local_path, const std::string &targetpath)
|
||||
{
|
||||
json j;
|
||||
|
||||
j["sequence_id"] = id;
|
||||
j["version"] = 1;
|
||||
j["peer_host"] = "studio";
|
||||
j["command"] = "get_project_file";
|
||||
j["file_rel_path"] = targetpath;
|
||||
|
||||
std::string param = j.dump();
|
||||
|
||||
DownloadRamFile(16, local_path, param);
|
||||
}
|
||||
|
||||
|
||||
void PrinterFileSystem::DownloadRamFile(int index, const std::string &local_path, const std::string & param)
|
||||
{
|
||||
std::shared_ptr<Download> download(new Download);
|
||||
download->local_path = local_path;
|
||||
|
||||
json req;
|
||||
req["path"] = "mem:/" + std::to_string(index);
|
||||
req["offset"] = 0;
|
||||
req["mem_dl_param_size"] = param.size();
|
||||
|
||||
m_download_seq = SendRequest<Progress>(
|
||||
FILE_DOWNLOAD, req,
|
||||
[download](json const &resp, Progress &prog, unsigned char const *data) -> int {
|
||||
size_t size = resp.value("size", 0);
|
||||
prog.size = resp["offset"];
|
||||
prog.total = resp["total"];
|
||||
|
||||
if (resp.contains("mem_dl_param_size")) {
|
||||
size_t s = resp["mem_dl_param_size"].get<size_t>();
|
||||
std::string json_str(reinterpret_cast<const char *>(data), s);
|
||||
// OutputDebugStringA(json_str.c_str());
|
||||
// OutputDebugStringA("\n");
|
||||
json mem_dl_json = json::parse(json_str);
|
||||
// download->mem_dl_param_size = size;
|
||||
if (!mem_dl_json.contains("result") || mem_dl_json["result"] == 1 ) {
|
||||
wxLogWarning("Download failed: result = 1");
|
||||
return ERROR_JSON;
|
||||
}
|
||||
if(mem_dl_json.contains("size") && mem_dl_json["size"] == 0 )
|
||||
return FILE_SIZE_ERR;
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
if (prog.size == 0 ) {
|
||||
download->ofs.open(download->local_path, std::ios::binary);
|
||||
if (!download->ofs) {
|
||||
download->error = last_system_error();
|
||||
wxLogWarning("DownloadImageFromRam open error: %s\n", wxString::FromUTF8(download->error));
|
||||
return FILE_OPEN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
download->ofs.write(reinterpret_cast<const char *>(data), size);
|
||||
if (!download->ofs) {
|
||||
download->error = last_system_error();
|
||||
wxLogWarning("DownloadImageFromRam write error: %s\n", wxString::FromUTF8(download->error));
|
||||
return FILE_READ_WRITE_ERR;
|
||||
}
|
||||
|
||||
download->boost_md5.process_bytes(data, size);
|
||||
|
||||
prog.size += size;
|
||||
download->total = prog.total;
|
||||
download->size = prog.size;
|
||||
|
||||
if (prog.size < prog.total) {
|
||||
return 0;
|
||||
}
|
||||
download->ofs.close();
|
||||
|
||||
std::string md5 = resp["file_md5"];
|
||||
boost::uuids::detail::md5::digest_type digest;
|
||||
download->boost_md5.get_digest(digest);
|
||||
for (int i = 0; i < 4; ++i) digest[i] = boost::endian::endian_reverse(digest[i]);
|
||||
std::string str_md5;
|
||||
const auto char_digest = reinterpret_cast<const char *>(&digest[0]);
|
||||
boost::algorithm::hex(char_digest, char_digest + sizeof(digest), std::back_inserter(str_md5));
|
||||
if (!boost::iequals(str_md5, md5)) {
|
||||
wxLogWarning("DownloadImageFromRam checksum error: %s != %s\n", str_md5, md5);
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::rename(download->local_path, download->local_path + ".tmp", ec);
|
||||
return FILE_CHECK_ERR;
|
||||
}
|
||||
return SUCCESS;
|
||||
},
|
||||
|
||||
[this, download](int result, Progress const &data) {
|
||||
//OutputDebugStringA(std::to_string(result).c_str());
|
||||
//OutputDebugStringA("\n");
|
||||
if (result == CONTINUE) { return; }
|
||||
std::string msg;
|
||||
if (result == SUCCESS) {
|
||||
if (std::filesystem::exists(download->local_path)) {
|
||||
m_download_states.emplace_back(true);
|
||||
BOOST_LOG_TRIVIAL(info) <<"DownloadImageFromRam finished: " << download->local_path << "result = " << result;
|
||||
}else{
|
||||
m_download_states.emplace_back(false);
|
||||
BOOST_LOG_TRIVIAL(warning) <<"DownloadImageFromRam finished, but file not exist: " << download->local_path << "result = " << result;
|
||||
}
|
||||
} else if (result != CONTINUE) {
|
||||
m_download_states.emplace_back(false);
|
||||
BOOST_LOG_TRIVIAL(warning) << "DownloadImageFromRam failed: " << download->error << "result = " << result;
|
||||
}
|
||||
|
||||
if(m_download_states.size() == 3){
|
||||
if(m_download_states[0] && m_download_states[1] && m_download_states[2]){
|
||||
SendChangedEvent(EVT_RAMDOWNLOAD, SUCCESS);
|
||||
}else{
|
||||
// FILE_NO_EXIST is not really error_code
|
||||
SendChangedEvent(EVT_RAMDOWNLOAD, FILE_NO_EXIST);
|
||||
}
|
||||
}else{
|
||||
BOOST_LOG_TRIVIAL(warning) << "m_download_states current size is : " << m_download_states.size();
|
||||
}
|
||||
},param);
|
||||
}
|
||||
|
||||
void PrinterFileSystem::SendExistedFile(){
|
||||
SendChangedEvent(EVT_RAMDOWNLOAD, SUCCESS);
|
||||
}
|
||||
void PrinterFileSystem::SendConnectFail(){
|
||||
SendChangedEvent(EVT_RAMDOWNLOAD, ERROR_PIPE);
|
||||
}
|
||||
|
||||
|
||||
void PrinterFileSystem::DownloadFiles(size_t index, std::string const &path)
|
||||
{
|
||||
if (index == (size_t) -1) {
|
||||
@@ -304,6 +448,10 @@ void PrinterFileSystem::DownloadFiles(size_t index, std::string const &path)
|
||||
DownloadNextFile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void PrinterFileSystem::DownloadCheckFiles(std::string const &path)
|
||||
{
|
||||
for (size_t i = 0; i < m_file_list.size(); ++i) {
|
||||
@@ -1280,7 +1428,7 @@ void PrinterFileSystem::CancelUploadTask(bool send_cancel_req)
|
||||
}
|
||||
}
|
||||
|
||||
boost::uint32_t PrinterFileSystem::SendRequest(int type, json const &req, callback_t2 const &callback)
|
||||
boost::uint32_t PrinterFileSystem::SendRequest(int type, json const &req, callback_t2 const &callback,const std::string& param)
|
||||
{
|
||||
if (m_session.tunnel == nullptr) {
|
||||
Retry();
|
||||
@@ -1294,6 +1442,13 @@ boost::uint32_t PrinterFileSystem::SendRequest(int type, json const &req, callba
|
||||
root["req"] = req;
|
||||
std::ostringstream oss;
|
||||
oss << root;
|
||||
|
||||
if (!param.empty()) {
|
||||
oss << "\n\n";
|
||||
oss << param;
|
||||
}
|
||||
// OutputDebugStringA(oss.str().c_str());
|
||||
// OutputDebugStringA("\n");
|
||||
auto msg = oss.str();
|
||||
boost::unique_lock l(m_mutex);
|
||||
m_messages.push_back(msg);
|
||||
|
||||
@@ -22,6 +22,7 @@ wxDECLARE_EVENT(EVT_FILE_CHANGED, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_SELECT_CHANGED, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_THUMBNAIL, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_DOWNLOAD, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_RAMDOWNLOAD, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_MEDIA_ABILITY_CHANGED, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_UPLOADING, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_UPLOAD_CHANGED, wxCommandEvent);
|
||||
@@ -183,6 +184,17 @@ public:
|
||||
|
||||
void DownloadFiles(size_t index, std::string const &path);
|
||||
|
||||
void GetPickImage(int id, const std::string &local_path, const std::string &path);
|
||||
|
||||
void GetPickImages(const std::vector<std::string> &local_paths, const std::vector<std::string> &targetpaths);
|
||||
|
||||
|
||||
void DownloadRamFile(int index, const std::string &local_path, const std::string ¶m);
|
||||
|
||||
void SendExistedFile();
|
||||
|
||||
void SendConnectFail();
|
||||
|
||||
void DownloadCheckFiles(std::string const &path);
|
||||
|
||||
bool DownloadCheckFile(size_t index);
|
||||
@@ -275,7 +287,7 @@ private:
|
||||
|
||||
typedef std::function<int(std::string &msg)> callback_t3;
|
||||
|
||||
template<typename T> boost::uint32_t SendRequest(int type, json const &req, Translator<T> const &translator, Callback<T> const &callback)
|
||||
template<typename T> boost::uint32_t SendRequest(int type, json const &req, Translator<T> const &translator, Callback<T> const &callback, const std::string ¶m = "")
|
||||
{
|
||||
auto c = [translator, callback, this](int result, json const &resp, unsigned char const *data) -> int
|
||||
{
|
||||
@@ -292,7 +304,7 @@ private:
|
||||
PostCallback<T>(callback, result, t);
|
||||
return result;
|
||||
};
|
||||
return SendRequest(type, req, c);
|
||||
return SendRequest(type, req, c, param);
|
||||
}
|
||||
|
||||
template<typename T> using Applier = std::function<void(T const &)>;
|
||||
@@ -322,7 +334,7 @@ private:
|
||||
InstallNotify(type, c);
|
||||
}
|
||||
|
||||
boost::uint32_t SendRequest(int type, json const &req, callback_t2 const &callback);
|
||||
boost::uint32_t SendRequest(int type, json const &req, callback_t2 const &callback, const std::string ¶m = "");
|
||||
|
||||
void InstallNotify(int type, callback_t2 const &callback);
|
||||
|
||||
@@ -365,6 +377,8 @@ private:
|
||||
size_t m_lock_end = 0;
|
||||
int m_task_flags = 0;
|
||||
|
||||
std::vector<bool> m_download_states;
|
||||
|
||||
private:
|
||||
struct Session
|
||||
{
|
||||
|
||||
697
src/slic3r/GUI/SkipPartCanvas.cpp
Normal file
697
src/slic3r/GUI/SkipPartCanvas.cpp
Normal file
@@ -0,0 +1,697 @@
|
||||
#include <GL/glew.h>
|
||||
#include "SkipPartCanvas.hpp"
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <expat.h>
|
||||
#include <earcut/earcut.hpp>
|
||||
#include <libslic3r/Color.hpp>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
|
||||
wxDEFINE_EVENT(EVT_ZOOM_PERCENT, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_CANVAS_PART, wxCommandEvent);
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
SkipPartCanvas::SkipPartCanvas(wxWindow *parent, const wxGLAttributes& dispAttrs)
|
||||
: wxGLCanvas(parent, dispAttrs) {
|
||||
context_ = new wxGLContext(this);
|
||||
this->Bind(wxEVT_PAINT, &SkipPartCanvas::OnPaint, this);
|
||||
this->Bind(wxEVT_MOUSEWHEEL, &SkipPartCanvas::OnMouseWheel, this);
|
||||
this->Bind(wxEVT_LEFT_DOWN, &SkipPartCanvas::OnMouseLeftDown, this);
|
||||
this->Bind(wxEVT_LEFT_DCLICK, &SkipPartCanvas::OnMouseLeftDown, this);
|
||||
this->Bind(wxEVT_LEFT_UP, &SkipPartCanvas::OnMouseLeftUp, this);
|
||||
this->Bind(wxEVT_RIGHT_DOWN, &SkipPartCanvas::OnMouseRightDown, this);
|
||||
this->Bind(wxEVT_RIGHT_UP, &SkipPartCanvas::OnMouseRightUp, this);
|
||||
this->Bind(wxEVT_SIZE, &SkipPartCanvas::OnSize, this);
|
||||
this->Bind(wxEVT_MOTION, &SkipPartCanvas::OnMouseMotion, this);
|
||||
}
|
||||
|
||||
void SkipPartCanvas::LoadPickImage(const std::string & path)
|
||||
{
|
||||
if(!std::filesystem::exists(path)) return;
|
||||
|
||||
auto ParseShapeId = [](cv::Mat image, const std::vector<std::vector<cv::Point>> &contours, const std::vector<cv::Vec4i> &hierarchy, int root_idx) -> uint32_t {
|
||||
cv::Mat mask = cv::Mat::zeros(image.size(), CV_8UC1);
|
||||
|
||||
cv::drawContours(mask, contours, root_idx, 255, cv::FILLED);
|
||||
|
||||
int child = hierarchy[root_idx][2];
|
||||
while (child != -1) {
|
||||
cv::drawContours(mask, contours, child, 0, cv::FILLED);
|
||||
child = hierarchy[child][0];
|
||||
}
|
||||
std::vector<cv::Vec3b> pixels;
|
||||
for (int y = 0; y < image.rows; ++y) {
|
||||
for (int x = 0; x < image.cols; ++x) {
|
||||
if (mask.at<uchar>(y, x)) { pixels.push_back(image.at<cv::Vec3b>(y, x)); }
|
||||
}
|
||||
}
|
||||
|
||||
std::map<cv::Vec3b, int, std::function<bool(const cv::Vec3b &, const cv::Vec3b &)>> colorCount(
|
||||
[](const cv::Vec3b &a, const cv::Vec3b &b) { return std::lexicographical_compare(a.val, a.val + 3, b.val, b.val + 3); });
|
||||
|
||||
for (auto &c : pixels) colorCount[c]++;
|
||||
|
||||
cv::Vec3b main_color;
|
||||
int max_count = 0;
|
||||
int total_count = 0;
|
||||
for (const auto &kv : colorCount) {
|
||||
if (kv.second > max_count) {
|
||||
max_count = kv.second;
|
||||
main_color = kv.first;
|
||||
}
|
||||
total_count += kv.second;
|
||||
}
|
||||
|
||||
SkipIdHelper helper{main_color[2], main_color[1], main_color[0]};
|
||||
helper.reverse();
|
||||
return (max_count * 2 > total_count) ? helper.value : 0;
|
||||
};
|
||||
|
||||
parts_state_.clear();
|
||||
parts_triangles_.clear();
|
||||
pick_parts_.clear();
|
||||
int preffered_w{FromDIP(400)}, preffered_h{FromDIP(400)};
|
||||
cv::Mat src_image = cv::imread(path, cv::IMREAD_UNCHANGED);
|
||||
cv::cvtColor(src_image, src_image, cv::COLOR_BGRA2BGR); // remove alpha
|
||||
float zoom_x{static_cast<float>(preffered_w) / src_image.cols};
|
||||
float zoom_y{static_cast<float>(preffered_h) / src_image.rows};
|
||||
float image_scale{0};
|
||||
if (abs(zoom_x - 1) > abs(zoom_y - 1))
|
||||
image_scale = zoom_x;
|
||||
else
|
||||
image_scale = zoom_y;
|
||||
image_view_scale_ = 1 / image_scale;
|
||||
pick_image_ = src_image;
|
||||
std::vector<cv::Mat> channels;
|
||||
cv::Mat gray; // convert to gray
|
||||
cv::cvtColor(pick_image_, gray, cv::COLOR_BGR2GRAY);
|
||||
cv::Mat mask; // convery to binary
|
||||
cv::threshold(gray, mask, 0, 255, cv::THRESH_BINARY);
|
||||
std::vector<std::vector<cv::Point>> pick_counters;
|
||||
std::vector<cv::Vec4i> hierarchy;
|
||||
cv::findContours(mask, pick_counters, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_TC89_KCOS);
|
||||
auto compute_depth = [&](int idx) {
|
||||
int depth = 0;
|
||||
while (hierarchy[idx][3] != -1) {
|
||||
depth++;
|
||||
idx = hierarchy[idx][3];
|
||||
}
|
||||
return depth;
|
||||
};
|
||||
for (int i = 0; i < pick_counters.size(); ++i) {
|
||||
int depth = compute_depth(i);
|
||||
int parent = hierarchy[i][3];
|
||||
if (parent != -1) continue;
|
||||
|
||||
auto id = ParseShapeId(pick_image_, pick_counters, hierarchy, i);
|
||||
if (id > 0) {
|
||||
std::vector<FloatPoint> flat_points;
|
||||
std::vector<std::vector<FloatPoint>> polygon;
|
||||
|
||||
// part body
|
||||
{
|
||||
polygon.emplace_back();
|
||||
for (const auto &pt : pick_counters[i]) {
|
||||
FloatPoint fp{pt.x * 1.0f, pt.y * 1.0f};
|
||||
polygon.back().push_back(fp);
|
||||
flat_points.push_back(fp);
|
||||
}
|
||||
int child = hierarchy[i][2];
|
||||
while (child != -1) {
|
||||
polygon.emplace_back();
|
||||
for (const auto &pt : pick_counters[child]) {
|
||||
FloatPoint fp{pt.x * 1.0f, pt.y * 1.0f};
|
||||
polygon.back().push_back(fp);
|
||||
flat_points.push_back(fp);
|
||||
}
|
||||
child = hierarchy[child][0];
|
||||
}
|
||||
std::vector<uint32_t> indices = mapbox::earcut<uint32_t>(polygon);
|
||||
std::vector<FloatPoint> final_counter;
|
||||
for (size_t j = 0; j < indices.size(); j += 3) {
|
||||
final_counter.push_back(flat_points[indices[j]]);
|
||||
final_counter.push_back(flat_points[indices[j + 1]]);
|
||||
final_counter.push_back(flat_points[indices[j + 2]]);
|
||||
}
|
||||
|
||||
parts_triangles_[id].emplace_back(final_counter);
|
||||
}
|
||||
// part outlines
|
||||
{
|
||||
pick_parts_[id].emplace_back(pick_counters[i]);
|
||||
int child = hierarchy[i][2];
|
||||
while (child != -1) {
|
||||
pick_parts_[id].emplace_back(pick_counters[child]);
|
||||
child = hierarchy[child][0];
|
||||
}
|
||||
}
|
||||
if (parts_state_.find(id) == parts_state_.end()) parts_state_.emplace(id, psUnCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkipPartCanvas::ZoomIn(const int zoom_percent)
|
||||
{
|
||||
SetZoomPercent(zoom_percent_ + zoom_percent);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SkipPartCanvas::ZoomOut(const int zoom_percent)
|
||||
{
|
||||
SetZoomPercent(zoom_percent_ - zoom_percent);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SkipPartCanvas::SwitchDrag(const bool drag_on)
|
||||
{
|
||||
fixed_draging_ = drag_on;
|
||||
AutoSetCursor();
|
||||
}
|
||||
|
||||
|
||||
void SkipPartCanvas::UpdatePartsInfo(const PartsInfo& parts)
|
||||
{
|
||||
for (auto const& part : parts) {
|
||||
if (auto res = parts_state_.find(part.first); res != parts_state_.end())
|
||||
res->second = part.second;
|
||||
}
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void DrawRoundedRect(float x, float y, float width, float height, float radius, const ColorRGB& color, int segments = 16)
|
||||
{
|
||||
glColor3f(color.r(), color.g(), color.b());
|
||||
|
||||
// 1. Draw center rectangle
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(x + radius, y + radius);
|
||||
glVertex2f(x + width - radius, y + radius);
|
||||
glVertex2f(x + width - radius, y + height - radius);
|
||||
glVertex2f(x + radius, y + height - radius);
|
||||
glEnd();
|
||||
|
||||
// 2. Draw side rectangles (excluding corners)
|
||||
glBegin(GL_QUADS);
|
||||
// Left
|
||||
glVertex2f(x, y + radius);
|
||||
glVertex2f(x + radius, y + radius);
|
||||
glVertex2f(x + radius, y + height - radius);
|
||||
glVertex2f(x, y + height - radius);
|
||||
|
||||
// Right
|
||||
glVertex2f(x + width - radius, y + radius);
|
||||
glVertex2f(x + width, y + radius);
|
||||
glVertex2f(x + width, y + height - radius);
|
||||
glVertex2f(x + width - radius, y + height - radius);
|
||||
|
||||
// Top
|
||||
glVertex2f(x + radius, y + height - radius);
|
||||
glVertex2f(x + width - radius, y + height - radius);
|
||||
glVertex2f(x + width - radius, y + height);
|
||||
glVertex2f(x + radius, y + height);
|
||||
|
||||
// Bottom
|
||||
glVertex2f(x + radius, y);
|
||||
glVertex2f(x + width - radius, y);
|
||||
glVertex2f(x + width - radius, y + radius);
|
||||
glVertex2f(x + radius, y + radius);
|
||||
glEnd();
|
||||
|
||||
// 3. Draw corners
|
||||
auto drawCorner = [&](float cx, float cy, float startAngle) {
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glVertex2f(cx, cy);
|
||||
for (int i = 0; i <= segments; ++i) {
|
||||
float angle = startAngle + (M_PI * 0.5f) * (float)i / segments;
|
||||
glVertex2f(cx + cosf(angle) * radius, cy + sinf(angle) * radius);
|
||||
}
|
||||
glEnd();
|
||||
};
|
||||
|
||||
drawCorner(x + radius, y + radius, M_PI); // bottom-left
|
||||
drawCorner(x + width - radius, y + radius, 1.5f * M_PI); // bottom-right
|
||||
drawCorner(x + width - radius, y + height - radius, 0.0f); // top-right
|
||||
drawCorner(x + radius, y + height - radius, 0.5f * M_PI); // top-left
|
||||
}
|
||||
|
||||
|
||||
void SkipPartCanvas::Render()
|
||||
{
|
||||
constexpr float border_w = 3.f;
|
||||
constexpr int uncheckd_stencil =1;
|
||||
constexpr int checkd_stencil = 2;
|
||||
constexpr int skipped_stencil = 3;
|
||||
|
||||
SetCurrent(*context_);
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
|
||||
int w, h;
|
||||
GetClientSize(&w, &h);
|
||||
#if defined(__APPLE__)
|
||||
double scale = GetDPIScaleFactor();
|
||||
glViewport(0, 0, w * scale, h * scale);
|
||||
#else
|
||||
glViewport(0, 0, w, h);
|
||||
#endif
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
auto view_rect = ViewPtToImagePt(wxPoint(w, h));
|
||||
glOrtho(offset_.x, view_rect.x, view_rect.y, offset_.y, -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glClearColor(parent_color_.r(), parent_color_.g(), parent_color_.b(), 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
float rx = offset_.x;
|
||||
float ry = offset_.y;
|
||||
float rw = view_rect.x - offset_.x;
|
||||
float rh = view_rect.y - offset_.y;
|
||||
float radius = std::min(rw, rh) * 0.05f;
|
||||
|
||||
DrawRoundedRect(rx, ry, rw, rh, radius, ColorRGB{0.9f, 0.9f, 0.9f});
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
auto draw_shape = [this, border_w](const int stencil, const PartState part_type, const ColorRGB& rgb) {
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glStencilFunc(GL_ALWAYS, stencil, 0xFF);
|
||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
|
||||
for (const auto& contour : parts_triangles_) {
|
||||
auto part_info = parts_state_.find(contour.first);
|
||||
if (part_info == parts_state_.end() || part_info->second != part_type)
|
||||
continue;
|
||||
glColor3f(1, 1, 1);
|
||||
for (const auto &contour_item : contour.second) {
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (size_t i = 0; i < contour_item.size(); i += 3) {
|
||||
glVertex2f(contour_item[i][0], contour_item[i][1]);
|
||||
glVertex2f(contour_item[i + 1][0], contour_item[i + 1][1]);
|
||||
glVertex2f(contour_item[i + 2][0], contour_item[i + 2][1]);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& contour : pick_parts_) {
|
||||
if (contour.first != this->hover_id_) continue;
|
||||
auto part_info = parts_state_.find(contour.first);
|
||||
if (part_info == parts_state_.end() || part_info->second != part_type)
|
||||
continue;
|
||||
|
||||
glColor3f(rgb.r(), rgb.g(), rgb.b());
|
||||
glLineWidth(border_w);
|
||||
for (const auto &contour_item : contour.second) {
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for (const auto &pt : contour_item) { glVertex2f(pt.x, pt.y); }
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
};
|
||||
// draw unchecked shapes
|
||||
// stencil1 => unchecked
|
||||
draw_shape(uncheckd_stencil, psUnCheck, ColorRGB{0, 174 / 255.f, 66 / 255.f});
|
||||
|
||||
// draw checked shapes
|
||||
// stencil2 => checked
|
||||
draw_shape(checkd_stencil, psChecked, ColorRGB{208 / 255.f, 27 / 255.f, 66 / 255.f});
|
||||
|
||||
// draw skipped shapes
|
||||
// stencil3 => skipped
|
||||
draw_shape(skipped_stencil, psSkipped, ColorRGB{95 / 255.f, 95 / 255.f, 95 / 255.f});
|
||||
|
||||
auto draw_mask = [this, view_rect, border_w, w, h](const int stencil, const PartState part_type,
|
||||
const ColorRGB& background, const ColorRGB& line, const ColorRGB& bound) {
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glStencilFunc(GL_EQUAL, stencil, 0xFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Don't change stencil
|
||||
glColor3f(background.r(), background.g(), background.b());
|
||||
glBegin(GL_POLYGON);
|
||||
glVertex2f(offset_.x, offset_.y);
|
||||
glVertex2f(offset_.x, view_rect.y);
|
||||
glVertex2f(view_rect.x, view_rect.y);
|
||||
glVertex2f(view_rect.x, offset_.y);
|
||||
glEnd();
|
||||
// draw main color
|
||||
glColor3f(line.r(), line.g(), line.b());
|
||||
// re-draw shape bound
|
||||
for (const auto& contour : pick_parts_) {
|
||||
auto part_info = parts_state_.find(contour.first);
|
||||
if (part_info == parts_state_.end() || part_info->second != part_type)
|
||||
continue;
|
||||
glColor3f(bound.r(), bound.g(), bound.b());
|
||||
glLineWidth(border_w);
|
||||
for (const auto &contour_item : contour.second) {
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for (const auto &pt : contour_item) { glVertex2f(pt.x, pt.y); }
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
draw_mask(checkd_stencil, psChecked, ColorRGB{239 / 255.f, 175 / 255.f, 175 / 255.f},
|
||||
ColorRGB{225 / 255.f, 71 / 255.f, 71 / 255.f}, ColorRGB{208 / 255.f, 27 / 255.f, 27 / 255.f});
|
||||
|
||||
draw_mask(skipped_stencil, psSkipped, ColorRGB{159 / 255.f, 159 / 255.f, 159 / 255.f},
|
||||
ColorRGB{95 / 255.f, 95 / 255.f, 95 / 255.f}, ColorRGB{95 / 255.f, 95 / 255.f, 95 / 255.f});
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
glPopAttrib();
|
||||
glFlush();
|
||||
}
|
||||
|
||||
void SkipPartCanvas::DebugLogLine(std::string str)
|
||||
{
|
||||
//if (!log_ctrl)
|
||||
// return;
|
||||
//log_ctrl->AppendText(str + "\n");
|
||||
}
|
||||
|
||||
void SkipPartCanvas::SendSelectEvent(int id, PartState state) {
|
||||
wxCommandEvent evt(EVT_CANVAS_PART);
|
||||
evt.SetExtraLong(id);
|
||||
evt.SetInt(static_cast<int>(state));
|
||||
wxPostEvent(this, evt);
|
||||
}
|
||||
void SkipPartCanvas::SendZoomEvent(int zoom_percent) {
|
||||
wxCommandEvent evt(EVT_ZOOM_PERCENT);
|
||||
evt.SetInt(zoom_percent_);
|
||||
wxPostEvent(this, evt);
|
||||
}
|
||||
|
||||
inline double SkipPartCanvas::Zoom() const
|
||||
{
|
||||
return zoom_percent_ / 100.0f;
|
||||
}
|
||||
|
||||
inline wxPoint SkipPartCanvas::ViewPtToImagePt(const wxPoint& view_pt) const
|
||||
{
|
||||
return wxPoint(view_pt.x * image_view_scale_ / Zoom(), view_pt.y * image_view_scale_ / Zoom()) + offset_;
|
||||
}
|
||||
|
||||
uint32_t SkipPartCanvas::GetIdAtImagePt(const wxPoint& image_pt) const
|
||||
{
|
||||
if (image_pt.x >= 0 && image_pt.x < pick_image_.cols
|
||||
&& image_pt.y >= 0 && image_pt.y < pick_image_.rows) {
|
||||
// at(row, col)=>at(y, x)
|
||||
cv::Vec3b bgr = pick_image_.at<cv::Vec3b>(image_pt.y, image_pt.x);
|
||||
SkipIdHelper helper{bgr[2], bgr[1], bgr[0]};
|
||||
helper.reverse();
|
||||
return helper.value;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline uint32_t SkipPartCanvas::GetIdAtViewPt(const wxPoint& view_pt) const
|
||||
{
|
||||
wxPoint pt_at_image = ViewPtToImagePt(view_pt);
|
||||
return GetIdAtImagePt(pt_at_image);
|
||||
}
|
||||
|
||||
void SkipPartCanvas::SetZoomPercent(const int value)
|
||||
{
|
||||
zoom_percent_ = std::clamp(value, 100, 1000);
|
||||
std::ostringstream oss;
|
||||
oss << "zoom to " << zoom_percent_;
|
||||
DebugLogLine(oss.str());
|
||||
|
||||
SendZoomEvent(zoom_percent_);
|
||||
}
|
||||
|
||||
void SkipPartCanvas::SetOffset(const wxPoint& value)
|
||||
{
|
||||
int w, h;
|
||||
GetClientSize(&w, &h);
|
||||
int max_w = static_cast<int>(w * (1 - 1 / Zoom())) >= 0 ? static_cast<int>(w * (1 - 1 / Zoom())) : 0;
|
||||
int max_h = static_cast<int>(w * (1 - 1 / Zoom())) >= 0 ? static_cast<int>(h * (1 - 1 / Zoom())) : 0;
|
||||
offset_.x = std::clamp(value.x, 0, max_w);
|
||||
offset_.y = std::clamp(value.y, 0, max_h);
|
||||
}
|
||||
|
||||
void SkipPartCanvas::AutoSetCursor()
|
||||
{
|
||||
if(is_draging_ || fixed_draging_)
|
||||
SetCursor(wxCursor(wxCURSOR_HAND));
|
||||
else
|
||||
SetCursor(wxCursor(wxCURSOR_NONE));
|
||||
}
|
||||
|
||||
void SkipPartCanvas::StartDrag(const wxPoint& mouse_pt)
|
||||
{
|
||||
drag_start_pt_ = mouse_pt;
|
||||
drag_start_offset_ = offset_;
|
||||
is_draging_ = true;
|
||||
AutoSetCursor();
|
||||
}
|
||||
|
||||
void SkipPartCanvas::ProcessDrag(const wxPoint& mouse_pt)
|
||||
{
|
||||
wxPoint drag_offset = (mouse_pt - drag_start_pt_) * image_view_scale_;
|
||||
SetOffset(- wxPoint(drag_offset.x / Zoom(), drag_offset.y / Zoom()) + drag_start_offset_);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SkipPartCanvas::ProcessHover(const wxPoint& mouse_pt)
|
||||
{
|
||||
auto id_at_mouse = GetIdAtViewPt(mouse_pt);
|
||||
int new_hover_id { -1 };
|
||||
auto part_state = parts_state_.find(id_at_mouse);
|
||||
if (part_state != parts_state_.end() && part_state->second == psUnCheck) {
|
||||
new_hover_id = id_at_mouse;
|
||||
};
|
||||
if (new_hover_id != this->hover_id_) {
|
||||
this->hover_id_ = new_hover_id;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void SkipPartCanvas::EndDrag()
|
||||
{
|
||||
is_draging_ = false;
|
||||
AutoSetCursor();
|
||||
}
|
||||
|
||||
void SkipPartCanvas::OnPaint(wxPaintEvent &event)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
if (!IsShown()) return;
|
||||
|
||||
SetCurrent(*context_);
|
||||
|
||||
Render();
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
void SkipPartCanvas::OnSize(wxSizeEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void SkipPartCanvas::OnMouseLeftDown(wxMouseEvent& event)
|
||||
{
|
||||
DebugLogLine("OnMouseLeftDown");
|
||||
if (!event.LeftIsDown()) {
|
||||
event.Skip();
|
||||
DebugLogLine("skip----OnMouseLeftDown");
|
||||
return;
|
||||
}
|
||||
if (fixed_draging_)
|
||||
StartDrag(wxPoint(event.GetX(), event.GetY()));
|
||||
left_down_ = true;
|
||||
}
|
||||
|
||||
void SkipPartCanvas::OnMouseLeftUp(wxMouseEvent& event)
|
||||
{
|
||||
DebugLogLine("OnMouseLeftUp");
|
||||
if (event.LeftIsDown() || !left_down_) {
|
||||
event.Skip();
|
||||
DebugLogLine("skip----OnMouseLeftUp");
|
||||
return;
|
||||
}
|
||||
auto id_at_mouse = GetIdAtViewPt(wxPoint(event.GetX(), event.GetY()));
|
||||
auto part_state = parts_state_.find(id_at_mouse);
|
||||
if (part_state != parts_state_.end() && part_state->second != psSkipped) {
|
||||
if (part_state->second == psUnCheck)
|
||||
part_state = parts_state_.insert_or_assign(part_state->first, psChecked).first;
|
||||
else
|
||||
part_state = parts_state_.insert_or_assign(part_state->first, psUnCheck).first;
|
||||
// if (select_callback_)
|
||||
// select_callback_(part_state->first, part_state->second);
|
||||
SendSelectEvent(part_state->first, part_state->second);
|
||||
}
|
||||
left_down_ = false;
|
||||
if (fixed_draging_)
|
||||
EndDrag();
|
||||
else {
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void SkipPartCanvas::OnMouseRightDown(wxMouseEvent& event)
|
||||
{
|
||||
DebugLogLine("OnMouseRightDown");
|
||||
if (!event.RightIsDown()) {
|
||||
event.Skip();
|
||||
DebugLogLine("skip----OnMouseRightDown");
|
||||
return;
|
||||
}
|
||||
StartDrag(wxPoint(event.GetX(), event.GetY()));
|
||||
}
|
||||
|
||||
void SkipPartCanvas::OnMouseRightUp(wxMouseEvent& event)
|
||||
{
|
||||
DebugLogLine("OnMouseRightUp");
|
||||
if (event.RightIsDown() || !is_draging_) {
|
||||
event.Skip();
|
||||
DebugLogLine("skip----OnMouseRightUp");
|
||||
return;
|
||||
}
|
||||
EndDrag();
|
||||
}
|
||||
|
||||
void SkipPartCanvas::OnMouseMotion(wxMouseEvent& event)
|
||||
{
|
||||
ProcessHover(wxPoint(event.GetX(), event.GetY()));
|
||||
if (!event.RightIsDown() && !(event.LeftIsDown() && fixed_draging_)) {
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
ProcessDrag(wxPoint(event.GetX(), event.GetY()));
|
||||
}
|
||||
|
||||
void SkipPartCanvas::OnMouseWheel(wxMouseEvent& event)
|
||||
{
|
||||
wxPoint view_mouse = wxPoint(event.GetX(), event.GetY());
|
||||
auto pre_image_pos = ViewPtToImagePt(view_mouse);
|
||||
SetZoomPercent(zoom_percent_ + 10 * (event.GetWheelRotation() / 120.0));
|
||||
auto now_image_pos = ViewPtToImagePt(view_mouse);
|
||||
SetOffset(offset_ - (now_image_pos - pre_image_pos));
|
||||
Refresh();
|
||||
}
|
||||
|
||||
// Base class with error messages management
|
||||
|
||||
void _BBS_3MF_Base::add_error(const std::string &error) const
|
||||
{
|
||||
boost::unique_lock l(mutex);
|
||||
m_errors.push_back(error);
|
||||
}
|
||||
void _BBS_3MF_Base::clear_errors() { m_errors.clear(); }
|
||||
|
||||
void _BBS_3MF_Base::log_errors()
|
||||
{
|
||||
for (const std::string &error : m_errors) BOOST_LOG_TRIVIAL(error) << error;
|
||||
}
|
||||
|
||||
|
||||
ModelSettingHelper::ModelSettingHelper(const std::string &path) : path_(path) {}
|
||||
|
||||
bool ModelSettingHelper::Parse()
|
||||
{
|
||||
boost::nowide::fstream fs(path_);
|
||||
if (!fs) {
|
||||
add_error("Failed to open file\n");
|
||||
return false;
|
||||
}
|
||||
XML_Parser parser = XML_ParserCreate(nullptr);
|
||||
if (!parser) {
|
||||
add_error("Unable to create parser");
|
||||
return false;
|
||||
}
|
||||
XML_SetUserData(parser, this);
|
||||
XML_SetElementHandler(parser, ModelSettingHelper::StartElementHandler, ModelSettingHelper::EndElementHandler);
|
||||
|
||||
try {
|
||||
char buffer[4000];
|
||||
while (fs.read(buffer, sizeof(buffer)) || fs.gcount() > 0) {
|
||||
auto ret = XML_Parse(parser, buffer, static_cast<int>(fs.gcount()), fs.eof());
|
||||
if (ret != XML_STATUS_OK) {
|
||||
add_error("return value of XML_Parse doesn't match XM_STATUS_OK");
|
||||
XML_ParserFree(parser);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
add_error(std::string("exception:") + e.what());
|
||||
XML_ParserFree(parser);
|
||||
return false;
|
||||
}
|
||||
XML_ParserFree(parser);
|
||||
return true;
|
||||
}
|
||||
|
||||
void XMLCALL ModelSettingHelper::StartElementHandler(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
ModelSettingHelper *self = static_cast<ModelSettingHelper *>(userData);
|
||||
if (strcmp(name, "plate") == 0) {
|
||||
self->context_.current_plate = PlateInfo(); // start a new plate
|
||||
self->context_.in_plate = true;
|
||||
} else if (strcmp(name, "metadata") == 0 && self->context_.in_plate) {
|
||||
std::string key, value;
|
||||
for (int i = 0; atts[i]; i += 2) {
|
||||
if (strcmp(atts[i], "key") == 0) key = atts[i + 1];
|
||||
if (strcmp(atts[i], "value") == 0) value = atts[i + 1];
|
||||
}
|
||||
if (key == "index") { self->context_.current_plate.index = std::stoi(value); }
|
||||
if (key == "label_object_enabled") { self->context_.current_plate.label_object_enabled = value == "true"; }
|
||||
} else if (strcmp(name, "object") == 0 && self->context_.in_plate) {
|
||||
ObjectInfo obj;
|
||||
for (int i = 0; atts[i]; i += 2) {
|
||||
if (strcmp(atts[i], "identify_id") == 0) obj.identify_id = atoi(atts[i + 1]);
|
||||
if (strcmp(atts[i], "name") == 0) obj.name = atts[i + 1];
|
||||
}
|
||||
self->context_.current_plate.objects.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void XMLCALL ModelSettingHelper::EndElementHandler(void *userData, const XML_Char *name)
|
||||
{
|
||||
ModelSettingHelper *self = static_cast<ModelSettingHelper *>(userData);
|
||||
if (strcmp(name, "plate") == 0 && self->context_.in_plate) {
|
||||
self->context_.plates.push_back(self->context_.current_plate);
|
||||
self->context_.current_plate = PlateInfo(); // reset
|
||||
self->context_.in_plate = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ObjectInfo> ModelSettingHelper::GetPlateObjects(int plate_idx) {
|
||||
for (const auto &plate : context_.plates) {
|
||||
if (plate.index == plate_idx) {
|
||||
return plate.objects;
|
||||
}
|
||||
}
|
||||
return std::vector<ObjectInfo>();
|
||||
}
|
||||
|
||||
bool ModelSettingHelper::GetLabelObjectEnabled(int plate_idx)
|
||||
{
|
||||
for (const auto &plate : context_.plates) {
|
||||
if (plate.index == plate_idx) { return plate.label_object_enabled; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ModelSettingHelper::DataHandler(const XML_Char *s, int len)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
169
src/slic3r/GUI/SkipPartCanvas.hpp
Normal file
169
src/slic3r/GUI/SkipPartCanvas.hpp
Normal file
@@ -0,0 +1,169 @@
|
||||
#ifndef SKIPPARTCANVAS_H
|
||||
#define SKIPPARTCANVAS_H
|
||||
#include <wx/wx.h>
|
||||
#include <wx/glcanvas.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <wx/textctrl.h>
|
||||
#include <vector>
|
||||
#include <expat.h>
|
||||
#include <libslic3r/Color.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include "PartSkipCommon.hpp"
|
||||
|
||||
wxDECLARE_EVENT(EVT_ZOOM_PERCENT, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_CANVAS_PART, wxCommandEvent);
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
using Coord = float;
|
||||
using FloatPoint = std::array<Coord, 2>;
|
||||
|
||||
|
||||
struct ObjectInfo {
|
||||
std::string name{""};
|
||||
int identify_id{-1};
|
||||
PartState state{psUnCheck};
|
||||
};
|
||||
|
||||
class SkipPartCanvas : public wxGLCanvas
|
||||
{
|
||||
union SkipIdHelper
|
||||
{
|
||||
uint32_t value = 0;
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t b;
|
||||
uint8_t g;
|
||||
uint8_t r;
|
||||
uint8_t _padding;
|
||||
};
|
||||
|
||||
uint8_t bytes[4];
|
||||
|
||||
SkipIdHelper() = default;
|
||||
|
||||
SkipIdHelper(uint8_t red, uint8_t green, uint8_t blue)
|
||||
: r(red), g(green), b(blue), _padding(0) {}
|
||||
|
||||
SkipIdHelper(uint32_t val): value(val){}
|
||||
void reverse() {
|
||||
uint8_t tmp{r};
|
||||
r = b;
|
||||
b = tmp;
|
||||
}
|
||||
};
|
||||
public:
|
||||
SkipPartCanvas(wxWindow *parent, const wxGLAttributes& dispAttrs);
|
||||
~SkipPartCanvas() = default;
|
||||
|
||||
void SetParentBackground(const ColorRGB& color) {
|
||||
parent_color_ = color;
|
||||
}
|
||||
|
||||
void LoadPickImage(const std::string& path);
|
||||
void ZoomIn(const int zoom_percent);
|
||||
void ZoomOut(const int zoom_percent);
|
||||
void SwitchDrag(const bool drag_on);
|
||||
void UpdatePartsInfo(const PartsInfo& parts);
|
||||
void SetZoomPercent(const int value);
|
||||
void SetOffset(const wxPoint &value);
|
||||
|
||||
wxTextCtrl* log_ctrl;
|
||||
protected:
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnSize(wxSizeEvent& event);
|
||||
void OnMouseLeftDown(wxMouseEvent& event);
|
||||
void OnMouseLeftUp(wxMouseEvent& event);
|
||||
void OnMouseRightDown(wxMouseEvent& event);
|
||||
void OnMouseRightUp(wxMouseEvent& event);
|
||||
void OnMouseMotion(wxMouseEvent& event);
|
||||
void OnMouseWheel(wxMouseEvent& event);
|
||||
private:
|
||||
wxGLContext* context_;
|
||||
cv::Mat pick_image_;
|
||||
std::unordered_map < uint32_t, std::vector<std::vector<FloatPoint>>> parts_triangles_;
|
||||
std::unordered_map < uint32_t, std::vector<std::vector<cv::Point>>> pick_parts_;
|
||||
std::unordered_map<uint32_t, PartState> parts_state_;
|
||||
bool gl_inited_{false};
|
||||
int zoom_percent_{100};
|
||||
wxPoint offset_{0,0};
|
||||
wxPoint drag_start_offset_{0,0};
|
||||
wxPoint drag_start_pt_{0,0};
|
||||
bool is_draging_{false};
|
||||
bool fixed_draging_{false};
|
||||
bool left_down_{false};
|
||||
ColorRGB parent_color_ = ColorRGB();
|
||||
int hover_id_{-1};
|
||||
double image_view_scale_{1};
|
||||
|
||||
void SendSelectEvent(int id, PartState state);
|
||||
void SendZoomEvent(int zoom_percent);
|
||||
|
||||
inline double Zoom() const;
|
||||
inline wxPoint ViewPtToImagePt(const wxPoint& view_pt) const;
|
||||
uint32_t GetIdAtImagePt(const wxPoint& image_pt) const;
|
||||
inline uint32_t GetIdAtViewPt(const wxPoint& view_pt) const;
|
||||
|
||||
void ProcessHover(const wxPoint& mouse_pt);
|
||||
void AutoSetCursor();
|
||||
void StartDrag(const wxPoint& mouse_pt);
|
||||
void ProcessDrag(const wxPoint& mouse_pt);
|
||||
void EndDrag();
|
||||
|
||||
void Render();
|
||||
|
||||
void DebugLogLine(std::string str);
|
||||
};
|
||||
|
||||
class _BBS_3MF_Base
|
||||
{
|
||||
mutable boost::mutex mutex;
|
||||
mutable std::vector<std::string> m_errors;
|
||||
|
||||
protected:
|
||||
void add_error(const std::string& error) const;
|
||||
void clear_errors();
|
||||
|
||||
public:
|
||||
void log_errors();
|
||||
};
|
||||
|
||||
struct PlateInfo
|
||||
{
|
||||
int index{-1};
|
||||
std::vector<ObjectInfo> objects;
|
||||
bool label_object_enabled = false;
|
||||
};
|
||||
|
||||
class ModelSettingHelper : public _BBS_3MF_Base
|
||||
{
|
||||
struct ParseContext
|
||||
{
|
||||
std::vector<PlateInfo> plates;
|
||||
PlateInfo current_plate;
|
||||
ObjectInfo temp_object;
|
||||
bool in_plate = false;
|
||||
};
|
||||
|
||||
public:
|
||||
ModelSettingHelper(const std::string &path);
|
||||
|
||||
bool Parse();
|
||||
std::vector<ObjectInfo> GetPlateObjects(int plate_idx);
|
||||
bool GetLabelObjectEnabled(int plate_idx);
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
ParseContext context_;
|
||||
|
||||
static void XMLCALL StartElementHandler(void *userData, const XML_Char *name, const XML_Char **atts);
|
||||
static void XMLCALL EndElementHandler(void *userData, const XML_Char *name);
|
||||
void DataHandler(const XML_Char *s, int len);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif //SKIPPARTCANVAS_H
|
||||
@@ -584,12 +584,6 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
|
||||
|
||||
bSizer_task_name->Add(task_name_panel, 0, wxEXPAND, FromDIP(5));
|
||||
|
||||
|
||||
/* wxFlexGridSizer *fgSizer_task = new wxFlexGridSizer(2, 2, 0, 0);
|
||||
fgSizer_task->AddGrowableCol(0);
|
||||
fgSizer_task->SetFlexibleDirection(wxVERTICAL);
|
||||
fgSizer_task->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);*/
|
||||
|
||||
m_printing_stage_value = new wxStaticText(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT | wxST_ELLIPSIZE_END);
|
||||
m_printing_stage_value->Wrap(-1);
|
||||
m_printing_stage_value->SetMaxSize(wxSize(FromDIP(800),-1));
|
||||
@@ -612,24 +606,34 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
|
||||
|
||||
m_staticText_profile_value->SetForegroundColour(0x6B6B6B);
|
||||
|
||||
auto progress_lr_panel = new wxPanel(parent, wxID_ANY);
|
||||
progress_lr_panel->SetBackgroundColour(*wxWHITE);
|
||||
|
||||
auto m_panel_progress = new wxPanel(parent, wxID_ANY);
|
||||
m_panel_progress->SetBackgroundColour(*wxWHITE);
|
||||
auto m_sizer_progressbar = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_gauge_progress = new ProgressBar(m_panel_progress, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize);
|
||||
m_gauge_progress = new ProgressBar(progress_lr_panel, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize);
|
||||
m_gauge_progress->SetValue(0);
|
||||
m_gauge_progress->SetHeight(PROGRESSBAR_HEIGHT);
|
||||
m_gauge_progress->SetMaxSize(wxSize(FromDIP(600), -1));
|
||||
m_panel_progress->SetSizer(m_sizer_progressbar);
|
||||
m_panel_progress->Layout();
|
||||
m_panel_progress->SetSize(wxSize(-1, FromDIP(24)));
|
||||
m_panel_progress->SetMaxSize(wxSize(-1, FromDIP(24)));
|
||||
|
||||
wxBoxSizer *bSizer_task_btn = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
bSizer_task_btn->Add(FromDIP(10), 0, 0);
|
||||
|
||||
m_button_pause_resume = new ScalableButton(m_panel_progress, wxID_ANY, "print_control_pause", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER,true);
|
||||
StateColor white_bg(std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Disabled), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Hovered), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Enabled),
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal));
|
||||
|
||||
m_button_partskip = new Button(progress_lr_panel, wxEmptyString, "print_control_partskip_disable", 0, 20, wxID_ANY);
|
||||
m_button_partskip->Enable(false);
|
||||
m_button_partskip->Hide();
|
||||
m_button_partskip->SetBackgroundColor(white_bg);
|
||||
m_button_partskip->SetIcon("print_control_partskip_disable");
|
||||
m_button_partskip->SetBorderColor(*wxWHITE);
|
||||
m_button_partskip->SetFont(Label::Body_12);
|
||||
m_button_partskip->SetCornerRadius(0);
|
||||
m_button_partskip->SetToolTip(_L("Parts Skip"));
|
||||
m_button_partskip->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { m_button_partskip->SetIcon("print_control_partskip_hover"); });
|
||||
m_button_partskip->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { m_button_partskip->SetIcon("print_control_partskip"); });
|
||||
|
||||
m_button_pause_resume = new ScalableButton(progress_lr_panel, wxID_ANY, "print_control_pause", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER,true);
|
||||
|
||||
m_button_pause_resume->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) {
|
||||
if (m_button_pause_resume->GetToolTipText() == _L("Pause")) {
|
||||
@@ -652,7 +656,7 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
|
||||
}
|
||||
});
|
||||
|
||||
m_button_abort = new ScalableButton(m_panel_progress, wxID_ANY, "print_control_stop", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true);
|
||||
m_button_abort = new ScalableButton(progress_lr_panel, wxID_ANY, "print_control_stop", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true);
|
||||
m_button_abort->SetToolTip(_L("Stop"));
|
||||
|
||||
m_button_abort->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) {
|
||||
@@ -663,19 +667,14 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
|
||||
m_button_abort->SetBitmap_("print_control_stop"); }
|
||||
);
|
||||
|
||||
m_sizer_progressbar->Add(m_gauge_progress, 1, wxALIGN_CENTER_VERTICAL, 0);
|
||||
m_sizer_progressbar->Add(0, 0, 0, wxEXPAND|wxLEFT, FromDIP(18));
|
||||
m_sizer_progressbar->Add(m_button_pause_resume, 0, wxALL, FromDIP(5));
|
||||
m_sizer_progressbar->Add(0, 0, 0, wxEXPAND|wxLEFT, FromDIP(18));
|
||||
m_sizer_progressbar->Add(m_button_abort, 0, wxALL, FromDIP(5));
|
||||
|
||||
wxBoxSizer *bSizer_buttons = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer *bSizer_text = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxPanel* penel_bottons = new wxPanel(parent);
|
||||
wxPanel* penel_text = new wxPanel(penel_bottons);
|
||||
wxBoxSizer *bSizer_finish_time = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxPanel* penel_text = new wxPanel(progress_lr_panel);
|
||||
wxPanel* penel_finish_time = new wxPanel(progress_lr_panel);
|
||||
|
||||
penel_text->SetBackgroundColour(*wxWHITE);
|
||||
penel_bottons->SetBackgroundColour(*wxWHITE);
|
||||
penel_finish_time->SetBackgroundColour(*wxWHITE);
|
||||
|
||||
wxBoxSizer *sizer_percent = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_percent->Add(0, 0, 1, wxEXPAND, 0);
|
||||
@@ -708,55 +707,65 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
|
||||
m_staticText_progress_left->SetFont(wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
|
||||
m_staticText_progress_left->SetForegroundColour(wxColour(146, 146, 146));
|
||||
|
||||
// Orca: display the end time of the print
|
||||
m_staticText_progress_end = new wxStaticText(penel_text, wxID_ANY, L("N/A"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_staticText_progress_end->Wrap(-1);
|
||||
m_staticText_progress_end->SetFont(
|
||||
wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
|
||||
m_staticText_progress_end->SetForegroundColour(wxColour(146, 146, 146));
|
||||
|
||||
//fgSizer_task->Add(bSizer_buttons, 0, wxEXPAND, 0);
|
||||
//fgSizer_task->Add(0, 0, 0, wxEXPAND, FromDIP(5));
|
||||
|
||||
wxPanel* panel_button_block = new wxPanel(penel_bottons, wxID_ANY);
|
||||
panel_button_block->SetMinSize(wxSize(TASK_BUTTON_SIZE.x * 2 + FromDIP(5) * 4, -1));
|
||||
panel_button_block->SetMinSize(wxSize(TASK_BUTTON_SIZE.x * 2 + FromDIP(5) * 4, -1));
|
||||
panel_button_block->SetSize(wxSize(TASK_BUTTON_SIZE.x * 2 + FromDIP(5) * 2, -1));
|
||||
panel_button_block->SetBackgroundColour(*wxWHITE);
|
||||
|
||||
m_staticText_layers = new wxStaticText(penel_text, wxID_ANY, _L("Layer: N/A"));
|
||||
m_staticText_layers->SetFont(wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
|
||||
m_staticText_layers->SetForegroundColour(wxColour(146, 146, 146));
|
||||
m_staticText_layers->Hide();
|
||||
|
||||
//bSizer_text->Add(m_staticText_progress_percent, 0, wxALL, 0);
|
||||
bSizer_text->Add(sizer_percent, 0, wxEXPAND, 0);
|
||||
bSizer_text->Add(sizer_percent_icon, 0, wxEXPAND, 0);
|
||||
bSizer_text->Add(0, 0, 1, wxEXPAND, 0);
|
||||
bSizer_text->Add(m_staticText_layers, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
bSizer_text->Add(m_staticText_layers, 0, wxALIGN_CENTER_VERTICAL | wxALL, 0);
|
||||
bSizer_text->Add(0, 0, 0, wxLEFT, FromDIP(20));
|
||||
bSizer_text->Add(m_staticText_progress_left, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
// Orca: display the end time of the print
|
||||
bSizer_text->Add(0, 0, 0, wxLEFT, FromDIP(8));
|
||||
bSizer_text->Add(m_staticText_progress_end, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
bSizer_text->Add(m_staticText_progress_left, 0, wxALIGN_CENTER_VERTICAL | wxALL, 0);
|
||||
|
||||
penel_text->SetMaxSize(wxSize(FromDIP(600), -1));
|
||||
// penel_text->SetMaxSize(wxSize(FromDIP(600), -1));
|
||||
penel_text->SetSizer(bSizer_text);
|
||||
penel_text->Layout();
|
||||
|
||||
bSizer_buttons->Add(penel_text, 1, wxEXPAND | wxALL, 0);
|
||||
bSizer_buttons->Add(panel_button_block, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
// Orca: display the end time of the print
|
||||
m_staticText_progress_end = new wxStaticText(penel_finish_time, wxID_ANY, L("N/A"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_staticText_progress_end->Wrap(-1);
|
||||
m_staticText_progress_end->SetFont(
|
||||
wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
|
||||
m_staticText_progress_end->SetForegroundColour(wxColour(146, 146, 146));
|
||||
bSizer_finish_time->Add(0, 0, 1, wxEXPAND, 0);
|
||||
bSizer_finish_time->Add(m_staticText_progress_end, 0, wxLEFT | wxEXPAND, 0);
|
||||
// penel_finish_time->SetMaxSize(wxSize(FromDIP(600), -1));
|
||||
penel_finish_time->SetSizer(bSizer_finish_time);
|
||||
penel_finish_time->Layout();
|
||||
|
||||
penel_bottons->SetSizer(bSizer_buttons);
|
||||
penel_bottons->Layout();
|
||||
auto progress_lr_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto progress_left_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto progress_right_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
progress_left_sizer->Add(penel_text, 0, wxEXPAND | wxALL, 0);
|
||||
progress_left_sizer->Add(m_gauge_progress, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(10));
|
||||
progress_left_sizer->Add(penel_finish_time, 0, wxEXPAND |wxALL, 0);
|
||||
// progress_left_sizer->SetMaxSize(wxSize(FromDIP(600), -1));
|
||||
|
||||
progress_right_sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(18));
|
||||
progress_right_sizer->Add(m_button_partskip, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(0));//5
|
||||
progress_right_sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(18));
|
||||
progress_right_sizer->Add(m_button_pause_resume, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(0));
|
||||
progress_right_sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(18));
|
||||
progress_right_sizer->Add(m_button_abort, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(0));
|
||||
progress_right_sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(18));
|
||||
|
||||
progress_lr_sizer->Add(progress_left_sizer, 1, wxEXPAND | wxALL, 0);
|
||||
progress_lr_sizer->Add(progress_right_sizer, 0, wxEXPAND | wxALL , 0);
|
||||
|
||||
progress_lr_panel->SetSizer(progress_lr_sizer);
|
||||
progress_lr_panel->SetMaxSize(wxSize(FromDIP(720), -1));
|
||||
|
||||
progress_lr_panel->Layout();
|
||||
progress_lr_panel->Fit();
|
||||
|
||||
bSizer_subtask_info->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(14));
|
||||
bSizer_subtask_info->Add(bSizer_task_name, 0, wxEXPAND|wxRIGHT, FromDIP(18));
|
||||
bSizer_subtask_info->Add(m_staticText_profile_value, 0, wxEXPAND | wxTOP, FromDIP(5));
|
||||
bSizer_subtask_info->Add(m_printing_stage_value, 0, wxEXPAND | wxTOP, FromDIP(5));
|
||||
bSizer_subtask_info->Add(penel_bottons, 0, wxEXPAND | wxTOP, FromDIP(10));
|
||||
bSizer_subtask_info->Add(m_panel_progress, 0, wxEXPAND|wxRIGHT, FromDIP(25));
|
||||
|
||||
bSizer_subtask_info->Add(progress_lr_panel, 0, wxEXPAND | wxTOP, FromDIP(5));
|
||||
|
||||
m_printing_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_printing_sizer->SetMinSize(wxSize(PAGE_MIN_WIDTH, -1));
|
||||
@@ -764,7 +773,6 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
|
||||
m_printing_sizer->Add(FromDIP(8), 0, 0, wxEXPAND, 0);
|
||||
m_printing_sizer->Add(bSizer_subtask_info, 1, wxALL | wxEXPAND, 0);
|
||||
|
||||
|
||||
m_staticline = new wxPanel( parent, wxID_ANY);
|
||||
m_staticline->SetBackgroundColour(wxColour(238,238,238));
|
||||
m_staticline->Layout();
|
||||
@@ -994,6 +1002,24 @@ void PrintingTaskPanel::reset_printing_value()
|
||||
this->set_plate_index(-1);
|
||||
}
|
||||
|
||||
void PrintingTaskPanel::enable_partskip_button(MachineObject* obj, bool enable)
|
||||
{
|
||||
int stage = 0;
|
||||
bool in_calibration_mode = false;
|
||||
if( obj && (obj->print_type == "system" || CalibUtils::get_calib_mode_by_name(obj->subtask_name, stage) != CalibMode::Calib_None)){
|
||||
in_calibration_mode = true;
|
||||
}
|
||||
|
||||
if (!enable || in_calibration_mode) {
|
||||
m_button_partskip->Enable(false);
|
||||
m_button_partskip->SetLabel("");
|
||||
m_button_partskip->SetIcon("print_control_partskip_disable");
|
||||
}else if(obj && obj->is_support_brtc){
|
||||
m_button_partskip->Enable(true);
|
||||
m_button_partskip->SetIcon("print_control_partskip");
|
||||
}
|
||||
}
|
||||
|
||||
void PrintingTaskPanel::enable_pause_resume_button(bool enable, std::string type)
|
||||
{
|
||||
if (!enable) {
|
||||
@@ -2248,6 +2274,7 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co
|
||||
//m_switch_fan->SetValue(false);
|
||||
|
||||
/* set default enable state */
|
||||
m_project_task_panel->enable_partskip_button(nullptr, false);
|
||||
m_project_task_panel->enable_pause_resume_button(false, "resume_disable");
|
||||
m_project_task_panel->enable_abort_button(false);
|
||||
|
||||
@@ -2278,6 +2305,7 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co
|
||||
|
||||
// Connect Events
|
||||
m_project_task_panel->get_bitmap_thumbnail()->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::refresh_thumbnail_webrequest), NULL, this);
|
||||
m_project_task_panel->get_partskip_button()->Connect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_subtask_partskip), NULL, this);
|
||||
m_project_task_panel->get_pause_resume_button()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_pause_resume), NULL, this);
|
||||
m_project_task_panel->get_abort_button()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_abort), NULL, this);
|
||||
m_project_task_panel->get_market_scoring_button()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_scoring), NULL, this);
|
||||
@@ -2338,6 +2366,7 @@ StatusPanel::~StatusPanel()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_project_task_panel->get_bitmap_thumbnail()->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::refresh_thumbnail_webrequest), NULL, this);
|
||||
m_project_task_panel->get_partskip_button()->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_subtask_partskip), NULL, this);
|
||||
m_project_task_panel->get_pause_resume_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_pause_resume), NULL, this);
|
||||
m_project_task_panel->get_abort_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_abort), NULL, this);
|
||||
m_project_task_panel->get_market_scoring_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_scoring), NULL, this);
|
||||
@@ -2472,6 +2501,35 @@ void StatusPanel::on_market_retry(wxCommandEvent &event)
|
||||
}
|
||||
}
|
||||
|
||||
void StatusPanel::update_partskip_button(MachineObject *obj) {
|
||||
if (!obj) return;
|
||||
|
||||
auto partskip_button = m_project_task_panel->get_partskip_button();
|
||||
if( obj->is_support_partskip ){
|
||||
partskip_button->Show();
|
||||
}else{
|
||||
partskip_button->Hide();
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "part skip: is_support_partskip: "<< obj->is_support_partskip;
|
||||
}
|
||||
|
||||
void StatusPanel::on_subtask_partskip(wxCommandEvent &event)
|
||||
{
|
||||
if (m_partskip_dlg == nullptr) {
|
||||
m_partskip_dlg = new PartSkipDialog(this->GetParent());
|
||||
}
|
||||
|
||||
auto dm = GUI::wxGetApp().getDeviceManager();
|
||||
m_partskip_dlg->InitSchedule(dm->get_selected_machine());
|
||||
BOOST_LOG_TRIVIAL(info) << "part skip: initial part skip dialog.";
|
||||
if(m_partskip_dlg->ShowModal() == wxID_OK){
|
||||
int cnt = m_partskip_dlg->GetAllSkippedPartsNum();
|
||||
m_project_task_panel->set_part_skipped_count(cnt);
|
||||
m_project_task_panel->set_part_skipped_dirty(5);
|
||||
BOOST_LOG_TRIVIAL(info) << "part skip: prepare to filter printer dirty data.";
|
||||
}
|
||||
}
|
||||
|
||||
void StatusPanel::on_subtask_pause_resume(wxCommandEvent &event)
|
||||
{
|
||||
if (obj) {
|
||||
@@ -3609,13 +3667,17 @@ void StatusPanel::update_subtask(MachineObject *obj)
|
||||
m_project_task_panel->show_layers_num(obj->is_support_layer_num);
|
||||
|
||||
update_model_info();
|
||||
update_partskip_button(obj);
|
||||
|
||||
if (obj->is_system_printing() || obj->is_in_calibration()) {
|
||||
reset_printing_values();
|
||||
} else if (obj->is_in_printing() || obj->print_status == "FINISH") {
|
||||
update_partskip_subtask(obj);
|
||||
|
||||
if (obj->is_in_prepare() || obj->print_status == "SLICING") {
|
||||
m_project_task_panel->market_scoring_hide();
|
||||
m_project_task_panel->get_request_failed_panel()->Hide();
|
||||
m_project_task_panel->enable_partskip_button(nullptr, false);
|
||||
m_project_task_panel->enable_abort_button(false);
|
||||
m_project_task_panel->enable_pause_resume_button(false, "pause_disable");
|
||||
wxString prepare_text;
|
||||
@@ -3657,7 +3719,7 @@ void StatusPanel::update_subtask(MachineObject *obj)
|
||||
} else {
|
||||
m_project_task_panel->enable_pause_resume_button(true, "pause");
|
||||
}
|
||||
|
||||
m_project_task_panel->enable_partskip_button(obj, true);
|
||||
// update printing stage
|
||||
m_project_task_panel->update_left_time(obj->mc_left_time);
|
||||
if (obj->subtask_) {
|
||||
@@ -3674,6 +3736,7 @@ void StatusPanel::update_subtask(MachineObject *obj)
|
||||
if (obj->is_printing_finished()) {
|
||||
obj->update_model_task();
|
||||
m_project_task_panel->enable_abort_button(false);
|
||||
m_project_task_panel->enable_partskip_button(nullptr, false);
|
||||
m_project_task_panel->enable_pause_resume_button(false, "resume_disable");
|
||||
// is makeworld subtask
|
||||
if (wxGetApp().has_model_mall() && obj->is_makeworld_subtask()) {
|
||||
@@ -3741,6 +3804,32 @@ void StatusPanel::update_subtask(MachineObject *obj)
|
||||
Layout();
|
||||
}
|
||||
|
||||
void StatusPanel::update_partskip_subtask(MachineObject *obj){
|
||||
if (!obj) return;
|
||||
if (!obj->subtask_) return;
|
||||
|
||||
auto partskip_button = m_project_task_panel->get_partskip_button();
|
||||
if (partskip_button) {
|
||||
int part_cnt = 0;
|
||||
if(m_project_task_panel->get_part_skipped_dirty() > 0){
|
||||
m_project_task_panel->set_part_skipped_dirty(m_project_task_panel->get_part_skipped_dirty() - 1);
|
||||
part_cnt = m_project_task_panel->get_part_skipped_count();
|
||||
BOOST_LOG_TRIVIAL(info) << "part skip: stop recv printer dirty data.";
|
||||
}else{
|
||||
part_cnt = obj->m_partskip_ids.size();
|
||||
BOOST_LOG_TRIVIAL(info) << "part skip: recv printer normal data.";
|
||||
}
|
||||
if (part_cnt > 0)
|
||||
partskip_button->SetLabel(wxString::Format(_L("(%d)"), part_cnt));
|
||||
else
|
||||
partskip_button->SetLabel("");
|
||||
}
|
||||
|
||||
if(m_partskip_dlg && m_partskip_dlg->IsShown()) {
|
||||
m_partskip_dlg->UpdatePartsStateFromPrinter(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void StatusPanel::update_cloud_subtask(MachineObject *obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
@@ -3807,6 +3896,7 @@ void StatusPanel::update_sdcard_subtask(MachineObject *obj)
|
||||
|
||||
void StatusPanel::reset_printing_values()
|
||||
{
|
||||
m_project_task_panel->enable_partskip_button(nullptr, false);
|
||||
m_project_task_panel->enable_pause_resume_button(false, "pause_disable");
|
||||
m_project_task_panel->enable_abort_button(false);
|
||||
m_project_task_panel->reset_printing_value();
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "Widgets/FilamentLoad.hpp"
|
||||
#include "Widgets/FanControl.hpp"
|
||||
#include "HMS.hpp"
|
||||
#include "PartSkipDialog.hpp"
|
||||
#include "DeviceErrorDialog.hpp"
|
||||
|
||||
class StepIndicator;
|
||||
@@ -260,7 +261,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
MachineObject* m_obj;
|
||||
MachineObject* m_obj{nullptr};
|
||||
ScalableBitmap m_thumbnail_placeholder;
|
||||
wxBitmap m_thumbnail_bmp_display;
|
||||
ScalableBitmap m_bitmap_use_time;
|
||||
@@ -292,6 +293,7 @@ private:
|
||||
wxStaticBitmap* m_bitmap_static_use_weight;
|
||||
ScalableButton* m_button_pause_resume;
|
||||
ScalableButton* m_button_abort;
|
||||
Button* m_button_partskip;
|
||||
Button* m_button_market_scoring;
|
||||
Button* m_button_clean;
|
||||
Button * m_button_market_retry;
|
||||
@@ -303,6 +305,10 @@ private:
|
||||
std::vector<ScalableButton *> m_score_star;
|
||||
bool m_star_count_dirty = false;
|
||||
|
||||
// partskip button
|
||||
int m_part_skipped_count{ 0 };
|
||||
int m_part_skipped_dirty{ 0 };
|
||||
|
||||
ProgressBar* m_gauge_progress;
|
||||
Label* m_error_text;
|
||||
PrintingTaskType m_type;
|
||||
@@ -317,6 +323,7 @@ public:
|
||||
void msw_rescale();
|
||||
|
||||
public:
|
||||
void enable_partskip_button(MachineObject* obj, bool enable);
|
||||
void enable_pause_resume_button(bool enable, std::string type);
|
||||
void enable_abort_button(bool enable);
|
||||
void update_subtask_name(wxString name);
|
||||
@@ -337,6 +344,7 @@ public:
|
||||
public:
|
||||
ScalableButton* get_abort_button() {return m_button_abort;};
|
||||
ScalableButton* get_pause_resume_button() {return m_button_pause_resume;};
|
||||
Button* get_partskip_button() { return m_button_partskip; };
|
||||
Button* get_market_scoring_button() {return m_button_market_scoring;};
|
||||
Button * get_market_retry_buttom() { return m_button_market_retry; };
|
||||
Button* get_clean_button() {return m_button_clean;};
|
||||
@@ -347,6 +355,10 @@ public:
|
||||
std::vector<ScalableButton *> &get_score_star() { return m_score_star; }
|
||||
bool get_star_count_dirty() { return m_star_count_dirty; }
|
||||
void set_star_count_dirty(bool dirty) { m_star_count_dirty = dirty; }
|
||||
int get_part_skipped_count() { return m_part_skipped_count; }
|
||||
void set_part_skipped_count(int count) { m_part_skipped_count = count; }
|
||||
int get_part_skipped_dirty() { return m_part_skipped_dirty; }
|
||||
void set_part_skipped_dirty(int dirty) { m_part_skipped_dirty = dirty; }
|
||||
void set_has_reted_text(bool has_rated);
|
||||
void paint(wxPaintEvent&);
|
||||
};
|
||||
@@ -432,6 +444,7 @@ protected:
|
||||
wxStaticText * m_staticText_progress_left;
|
||||
wxStaticText * m_staticText_layers;
|
||||
Button * m_button_report;
|
||||
Button * m_button_partskip;
|
||||
ScalableButton *m_button_pause_resume;
|
||||
ScalableButton *m_button_abort;
|
||||
Button * m_button_clean;
|
||||
@@ -526,6 +539,7 @@ protected:
|
||||
StaticBox* m_filament_load_box;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void on_subtask_partskip(wxCommandEvent &event) { event.Skip(); }
|
||||
virtual void on_subtask_pause_resume(wxCommandEvent &event) { event.Skip(); }
|
||||
virtual void on_subtask_abort(wxCommandEvent &event) { event.Skip(); }
|
||||
virtual void on_lamp_switch(wxCommandEvent &event) { event.Skip(); }
|
||||
@@ -612,6 +626,7 @@ protected:
|
||||
FanControlPopupNew* m_fan_control_popup{nullptr};
|
||||
|
||||
ExtrusionCalibration *m_extrusion_cali_dlg{nullptr};
|
||||
PartSkipDialog *m_partskip_dlg{nullptr};
|
||||
|
||||
wxString m_request_url;
|
||||
bool m_start_loading_thumbnail = false;
|
||||
@@ -652,6 +667,7 @@ protected:
|
||||
|
||||
void on_market_scoring(wxCommandEvent &event);
|
||||
void on_market_retry(wxCommandEvent &event);
|
||||
void on_subtask_partskip(wxCommandEvent &event);
|
||||
void on_subtask_pause_resume(wxCommandEvent &event);
|
||||
void on_subtask_abort(wxCommandEvent &event);
|
||||
void on_print_error_clean(wxCommandEvent &event);
|
||||
@@ -728,6 +744,7 @@ protected:
|
||||
void update_basic_print_data(bool def = false);
|
||||
void update_model_info();
|
||||
void update_subtask(MachineObject* obj);
|
||||
void update_partskip_subtask(MachineObject *obj);
|
||||
void update_cloud_subtask(MachineObject *obj);
|
||||
void update_sdcard_subtask(MachineObject *obj);
|
||||
void update_temp_ctrl(MachineObject *obj);
|
||||
@@ -747,6 +764,9 @@ protected:
|
||||
void update_camera_state(MachineObject* obj);
|
||||
bool show_vcamera = false;
|
||||
|
||||
// partskip button
|
||||
void update_partskip_button(MachineObject* obj);
|
||||
|
||||
public:
|
||||
void update_error_message();
|
||||
|
||||
|
||||
@@ -2529,7 +2529,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("raft_first_layer_expansion", "support_settings_support#initial-layer-expansion");
|
||||
optgroup->append_single_option_line("support_on_build_plate_only", "support_settings_support#on-build-plate-only");
|
||||
optgroup->append_single_option_line("support_critical_regions_only", "support_settings_support#support-critical-regions-only");
|
||||
optgroup->append_single_option_line("support_remove_small_overhang", "support_settings_support#remove-small-overhangs");
|
||||
optgroup->append_single_option_line("support_remove_small_overhang", "support_settings_support#ignore-small-overhangs");
|
||||
//optgroup->append_single_option_line("enforce_support_layers", "support_settings_support");
|
||||
|
||||
optgroup = page->new_optgroup(L("Raft"), L"param_raft");
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
AnimaIcon::AnimaIcon(wxWindow *parent, wxWindowID id, std::vector<std::string> img_list, std::string img_enable, int ivt)
|
||||
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize), m_ivt(ivt)
|
||||
{
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
SetBackgroundColour((wxColour(255, 255, 255)));
|
||||
m_size = 20;
|
||||
m_size = 25;
|
||||
|
||||
//add ScalableBitmap
|
||||
for (const auto &filename : img_list) m_images.emplace_back(create_scaled_bitmap(filename, this, m_size));
|
||||
@@ -47,12 +48,13 @@ AnimaIcon::AnimaIcon(wxWindow *parent, wxWindowID id, std::vector<std::string> i
|
||||
SetCursor(wxCursor(wxCURSOR_ARROW));
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
sizer->Add(m_bitmap, 0, wxALIGN_CENTER, 0);
|
||||
SetSizer(sizer);
|
||||
SetSize(wxSize(FromDIP(m_size), FromDIP(m_size)));
|
||||
SetMaxSize(wxSize(FromDIP(m_size), FromDIP(m_size)));
|
||||
SetMinSize(wxSize(FromDIP(m_size), FromDIP(m_size)));
|
||||
Refresh();
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
Play();
|
||||
}
|
||||
|
||||
@@ -73,5 +75,3 @@ void AnimaIcon::Enable()
|
||||
{
|
||||
if (m_bitmap) { m_bitmap->SetBitmap(m_image_enable); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -813,7 +813,7 @@ void ProgressDialog::DoSetSize(int x, int y, int width, int height, int sizeFlag
|
||||
// m_block_right->SetPosition(wxPoint(PROGRESSDIALOG_GAUGE_SIZE.x - 2, 0));
|
||||
//}
|
||||
#endif
|
||||
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
||||
wxDialog::DoSetSize(x, y, width, height, sizeFlags);
|
||||
}
|
||||
|
||||
void ProgressDialog::DisableOtherWindows()
|
||||
|
||||
Reference in New Issue
Block a user