update slic3r

This commit is contained in:
QIDI TECH
2024-11-28 15:19:12 +08:00
parent a26696f35e
commit 7eb6543991
196 changed files with 18701 additions and 3803 deletions

View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"charconv": "cpp"
}
}

View File

@@ -21,14 +21,39 @@ static const std::string temp_gcode_path = temp_dir + "/temp.gcode";
static const std::string path = temp_dir + "/test.3mf";
static const std::string config_3mf_path = temp_dir + "/test_config.3mf";
static std::string MachineBedTypeString[5] = {
static std::string MachineBedTypeString[6] = {
"auto",
"pc",
"ep",
"pei",
"pte"
"pte",
"suprtack"
};
void get_default_k_n_value(const std::string &filament_id, float &k, float &n)
{
if (filament_id.compare("GFG00") == 0) {
// PETG
k = 0.04;
n = 1.0;
} else if (filament_id.compare("GFB00") == 0 || filament_id.compare("GFB50") == 0) {
// ABS
k = 0.04;
n = 1.0;
} else if (filament_id.compare("GFU01") == 0) {
// TPU
k = 0.2;
n = 1.0;
} else if (filament_id.compare("GFB01") == 0) {
// ASA
k = 0.04;
n = 1.0;
} else {
// PLA , other
k = 0.02;
n = 1.0;
}
}
std::string get_calib_mode_name(CalibMode cali_mode, int stage)
{
@@ -296,7 +321,7 @@ static void read_model_from_file(const std::string& input_file, Model& model)
std::vector<Preset *> project_presets;
model = Model::read_from_file(input_file, &config, &config_substitutions, strategy, &plate_data_src, &project_presets,
&is_qdt_3mf, &file_version, nullptr, nullptr, nullptr, nullptr, nullptr, plate_to_slice);
&is_qdt_3mf, &file_version, nullptr, nullptr, nullptr, plate_to_slice);
model.add_default_instances();
for (auto object : model.objects)
@@ -1038,9 +1063,9 @@ bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f
if (params.mode == CalibMode::Calib_PA_Pattern) {
ModelInstance *instance = model->objects[0]->instances[0];
Vec3d offset = model->calib_pa_pattern->get_start_offset() +
Vec3d(model->calib_pa_pattern->handle_xy_size() / 2, -model->calib_pa_pattern->handle_xy_size() / 2 - model->calib_pa_pattern->handle_spacing(), 0);
instance->set_offset(offset);
instance->set_offset(Axis::X, model->calib_pa_pattern->get_start_offset().x() + model->calib_pa_pattern->handle_xy_size() / 2);
instance->set_offset(Axis::Y, model->calib_pa_pattern->get_start_offset().y() - model->calib_pa_pattern->handle_xy_size() / 2 - model->calib_pa_pattern->handle_spacing());
}
else if (model->objects.size() == 1) {
ModelInstance *instance = model->objects[0]->instances[0];
@@ -1125,7 +1150,7 @@ bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f
const ModelVolume &model_volume = *model_object.volumes[volume_idx];
for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) {
const ModelInstance &model_instance = *model_object.instances[instance_idx];
glvolume_collection.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, "volume", true, false, true);
glvolume_collection.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, "volume", true, false, true, false);
glvolume_collection.volumes.back()->set_render_color( new_color[0], new_color[1], new_color[2], new_color[3]);
glvolume_collection.volumes.back()->set_color(new_color);
//glvolume_collection.volumes.back()->printable = model_instance.printable;

View File

@@ -74,5 +74,7 @@ private:
static void send_to_print(const CalibInfo &calib_info, wxString& error_message, int flow_ratio_mode = 0); // 0: none 1: coarse 2: fine
};
extern void get_default_k_n_value(const std::string &filament_id, float &k, float &n);
}
}

View File

@@ -1,4 +1,5 @@
#include "FontUtils.hpp"
//#define STB_TRUETYPE_IMPLEMENTATION
#include "imgui/imstb_truetype.h"
#include "libslic3r/Utils.hpp"
#include <boost/log/trivial.hpp>
@@ -58,8 +59,6 @@ std::string get_file_path(const wxFont &font)
return path_str;
}
#endif // __APPLE__
using fontinfo_opt = std::optional<stbtt_fontinfo>;
std::string get_human_readable_name(const wxFont &font)
{
@@ -72,6 +71,8 @@ std::string get_human_readable_name(const wxFont &font)
}
}
using fontinfo_opt = std::optional<stbtt_fontinfo>;
fontinfo_opt load_font_info(const unsigned char *data, unsigned int index)
{
int font_offset = stbtt_GetFontOffsetForIndex(data, index);

View File

@@ -70,8 +70,8 @@ struct CurlGlobalInit
else
message = (boost::format("use system SSL certificate: %1%") % bundle).str();
message += "\n" + (boost::format("To manually specify the system certificate store, "
"set the %1% environment variable to the correct CA and restart the application") % SSL_CA_FILE).str();
message += "\n" + (boost::format("To manually specify the system certificate store, "
"set the %1% environment variable to the correct CA and restart the application.") % SSL_CA_FILE).str();
}
#endif // OPENSSL_CERT_OVERRIDE

View File

@@ -75,9 +75,11 @@ func_build_logout_cmd NetworkAgent::build_logout_cmd_ptr = nullptr
func_build_login_info NetworkAgent::build_login_info_ptr = nullptr;
func_get_model_id_from_desgin_id NetworkAgent::get_model_id_from_desgin_id_ptr = nullptr;
func_ping_bind NetworkAgent::ping_bind_ptr = nullptr;
func_bind_detect NetworkAgent::bind_detect_ptr = nullptr;
func_set_server_callback NetworkAgent::set_server_callback_ptr = nullptr;
func_bind NetworkAgent::bind_ptr = nullptr;
func_unbind NetworkAgent::unbind_ptr = nullptr;
func_get_qidilab_host NetworkAgent::get_qidilab_host_ptr = nullptr;
func_get_qiditech_host NetworkAgent::get_qiditech_host_ptr = nullptr;
func_get_user_selected_machine NetworkAgent::get_user_selected_machine_ptr = nullptr;
func_set_user_selected_machine NetworkAgent::set_user_selected_machine_ptr = nullptr;
func_start_print NetworkAgent::start_print_ptr = nullptr;
@@ -145,7 +147,6 @@ NetworkAgent::~NetworkAgent()
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", this %1%, network_agent=%2%, destroy_agent_ptr=%3%, ret %4%")%this %network_agent %destroy_agent_ptr %ret;
}
//1.9.5
std::string NetworkAgent::get_libpath_in_current_directory(std::string library_name)
{
std::string lib_path;
@@ -170,6 +171,7 @@ std::string NetworkAgent::get_libpath_in_current_directory(std::string library_n
return lib_path;
}
int NetworkAgent::initialize_network_module(bool using_backup)
{
//int ret = -1;
@@ -195,8 +197,7 @@ int NetworkAgent::initialize_network_module(bool using_backup)
::MultiByteToWideChar(CP_UTF8, NULL, library.c_str(), strlen(library.c_str()) + 1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
netwoking_module = LoadLibrary(lib_wstr);
}*/
//1.9.5
if (!netwoking_module) {
if (!netwoking_module) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", try load library directly from current directory");
std::string library_path = get_libpath_in_current_directory(std::string(QIDI_NETWORK_LIBRARY));
@@ -285,10 +286,12 @@ int NetworkAgent::initialize_network_module(bool using_backup)
build_logout_cmd_ptr = reinterpret_cast<func_build_logout_cmd>(get_network_function("qidi_network_build_logout_cmd"));
build_login_info_ptr = reinterpret_cast<func_build_login_info>(get_network_function("qidi_network_build_login_info"));
ping_bind_ptr = reinterpret_cast<func_ping_bind>(get_network_function("qidi_network_ping_bind"));
bind_detect_ptr = reinterpret_cast<func_bind_detect>(get_network_function("qidi_network_bind_detect"));
set_server_callback_ptr = reinterpret_cast<func_set_server_callback>(get_network_function("qidi_network_set_server_callback"));
get_model_id_from_desgin_id_ptr = reinterpret_cast<func_get_model_id_from_desgin_id>(get_network_function("qidi_network_get_model_id_from_desgin_id"));
bind_ptr = reinterpret_cast<func_bind>(get_network_function("qidi_network_bind"));
unbind_ptr = reinterpret_cast<func_unbind>(get_network_function("qidi_network_unbind"));
get_qidilab_host_ptr = reinterpret_cast<func_get_qidilab_host>(get_network_function("qidi_network_get_qidilab_host"));
get_qiditech_host_ptr = reinterpret_cast<func_get_qiditech_host>(get_network_function("qidi_network_get_qiditech_host"));
get_user_selected_machine_ptr = reinterpret_cast<func_get_user_selected_machine>(get_network_function("qidi_network_get_user_selected_machine"));
set_user_selected_machine_ptr = reinterpret_cast<func_set_user_selected_machine>(get_network_function("qidi_network_set_user_selected_machine"));
start_print_ptr = reinterpret_cast<func_start_print>(get_network_function("qidi_network_start_print"));
@@ -410,7 +413,7 @@ int NetworkAgent::unload_network_module()
ping_bind_ptr = nullptr;
bind_ptr = nullptr;
unbind_ptr = nullptr;
get_qidilab_host_ptr = nullptr;
get_qiditech_host_ptr = nullptr;
get_user_selected_machine_ptr = nullptr;
set_user_selected_machine_ptr = nullptr;
start_print_ptr = nullptr;
@@ -456,7 +459,7 @@ int NetworkAgent::unload_network_module()
put_rating_picture_oss_ptr = nullptr;
put_model_mall_rating_url_ptr = nullptr;
get_model_mall_rating_result_ptr = nullptr;
get_mw_user_preference_ptr = nullptr;
get_mw_user_4ulist_ptr = nullptr;
@@ -485,7 +488,6 @@ void* NetworkAgent::get_qidi_source_entry()
memset(lib_wstr, 0, sizeof(lib_wstr));
::MultiByteToWideChar(CP_UTF8, NULL, library.c_str(), strlen(library.c_str())+1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
source_module = LoadLibrary(lib_wstr);
//1.9.5
if (!source_module) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", try load QIDISource directly from current directory");
std::string library_path = get_libpath_in_current_directory(std::string(QIDI_SOURCE_LIBRARY));
@@ -927,11 +929,11 @@ bool NetworkAgent::is_user_login()
return ret;
}
int NetworkAgent::user_logout()
int NetworkAgent::user_logout(bool request)
{
int ret = 0;
if (network_agent && user_logout_ptr) {
ret = user_logout_ptr(network_agent);
ret = user_logout_ptr(network_agent, request);
if (ret)
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%")%network_agent %ret;
}
@@ -1025,6 +1027,30 @@ int NetworkAgent::ping_bind(std::string ping_code)
return ret;
}
int NetworkAgent::bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect)
{
int ret = 0;
if (network_agent && bind_detect_ptr) {
ret = bind_detect_ptr(network_agent, dev_ip, sec_link, detect);
if (ret)
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_ip=%3%")
% network_agent % ret % dev_ip;
}
return ret;
}
int NetworkAgent::set_server_callback(OnServerErrFn fn)
{
int ret = 0;
if (network_agent && set_server_callback_ptr) {
ret = set_server_callback_ptr(network_agent, fn);
if (ret)
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%")
% network_agent % ret;
}
return ret;
}
int NetworkAgent::bind(std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn)
{
int ret = 0;
@@ -1048,11 +1074,11 @@ int NetworkAgent::unbind(std::string dev_id)
return ret;
}
std::string NetworkAgent::get_qidilab_host()
std::string NetworkAgent::get_qiditech_host()
{
std::string ret;
if (network_agent && get_qidilab_host_ptr) {
ret = get_qidilab_host_ptr(network_agent);
if (network_agent && get_qiditech_host_ptr) {
ret = get_qiditech_host_ptr(network_agent);
}
return ret;
}

View File

@@ -45,7 +45,7 @@ typedef int (*func_send_message_to_printer)(void *agent, std::string dev_id, std
typedef bool (*func_start_discovery)(void *agent, bool start, bool sending);
typedef int (*func_change_user)(void *agent, std::string user_info);
typedef bool (*func_is_user_login)(void *agent);
typedef int (*func_user_logout)(void *agent);
typedef int (*func_user_logout)(void *agent, bool request);
typedef std::string (*func_get_user_id)(void *agent);
typedef std::string (*func_get_user_name)(void *agent);
typedef std::string (*func_get_user_avatar)(void *agent);
@@ -55,9 +55,11 @@ typedef std::string (*func_build_logout_cmd)(void *agent);
typedef std::string (*func_build_login_info)(void *agent);
typedef int (*func_get_model_id_from_desgin_id)(void *agent, std::string& desgin_id, std::string& model_id);
typedef int (*func_ping_bind)(void *agent, std::string ping_code);
typedef int (*func_bind_detect)(void *agent, std::string dev_ip, std::string sec_link, detectResult& detect);
typedef int (*func_set_server_callback)(void *agent, OnServerErrFn fn);
typedef int (*func_bind)(void *agent, std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn);
typedef int (*func_unbind)(void *agent, std::string dev_id);
typedef std::string (*func_get_qidilab_host)(void *agent);
typedef std::string (*func_get_qiditech_host)(void *agent);
typedef std::string (*func_get_user_selected_machine)(void *agent);
typedef int (*func_set_user_selected_machine)(void *agent, std::string dev_id);
typedef int (*func_start_print)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
@@ -115,7 +117,7 @@ class NetworkAgent
{
public:
static std::string get_libpath_in_current_directory(std::string library_name); //1.9.5
static std::string get_libpath_in_current_directory(std::string library_name);
static int initialize_network_module(bool using_backup = false);
static int unload_network_module();
#if defined(_MSC_VER) || defined(_WIN32)
@@ -162,7 +164,7 @@ public:
bool start_discovery(bool start, bool sending);
int change_user(std::string user_info);
bool is_user_login();
int user_logout();
int user_logout(bool request = false);
std::string get_user_id();
std::string get_user_name();
std::string get_user_avatar();
@@ -172,9 +174,11 @@ public:
std::string build_login_info();
int get_model_id_from_desgin_id(std::string& desgin_id, std::string& model_id);
int ping_bind(std::string ping_code);
int bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect);
int set_server_callback(OnServerErrFn fn);
int bind(std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn);
int unbind(std::string dev_id);
std::string get_qidilab_host();
std::string get_qiditech_host();
std::string get_user_selected_machine();
int set_user_selected_machine(std::string dev_id);
int start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
@@ -225,6 +229,7 @@ public:
int get_mw_user_preference(std::function<void(std::string)> callback);
int get_mw_user_4ulist(int seed, int limit, std::function<void(std::string)> callback);
void *get_network_agent() { return network_agent; }
private:
bool enable_track = false;
@@ -278,9 +283,11 @@ private:
static func_build_login_info build_login_info_ptr;
static func_get_model_id_from_desgin_id get_model_id_from_desgin_id_ptr;
static func_ping_bind ping_bind_ptr;
static func_bind_detect bind_detect_ptr;
static func_set_server_callback set_server_callback_ptr;
static func_bind bind_ptr;
static func_unbind unbind_ptr;
static func_get_qidilab_host get_qidilab_host_ptr;
static func_get_qiditech_host get_qiditech_host_ptr;
static func_get_user_selected_machine get_user_selected_machine_ptr;
static func_set_user_selected_machine set_user_selected_machine_ptr;
static func_start_print start_print_ptr;

View File

@@ -51,7 +51,8 @@ namespace Slic3r {
static const char *INDEX_FILENAME = "index.idx";
static const char *TMP_EXTENSION = ".data";
static const char *PRESET_SUBPATH = "presets";
static const char *PLUGINS_SUBPATH = "plugins";
void copy_file_fix(const fs::path &source, const fs::path &target)
{
@@ -80,13 +81,13 @@ void copy_directory_fix(const fs::path &source, const fs::path &target)
if (fs::exists(target))
fs::remove_all(target);
fs::create_directories(target);
for (auto &dir_entry : boost::filesystem::directory_iterator(source))
for (auto &dir_entry : fs::directory_iterator(source))
{
std::string source_file = dir_entry.path().string();
std::string name = dir_entry.path().filename().string();
std::string target_file = target.string() + "/" + name;
if (boost::filesystem::is_directory(dir_entry)) {
if (fs::is_directory(dir_entry)) {
const auto target_path = target / name;
copy_directory_fix(dir_entry, target_path);
}
@@ -220,6 +221,7 @@ struct PresetUpdater::priv
std::string version;
std::string description;
std::string url;
std::string vendor;
bool force{false};
std::string cache_root;
std::vector<std::string> sub_caches;
@@ -234,8 +236,14 @@ struct PresetUpdater::priv
void prune_tmps() const;
void sync_version() const;
void parse_version_string(const std::string& body) const;
void sync_resources(std::string http_url, std::map<std::string, Resource> &resources, bool check_patch = false, std::string current_version="", std::string changelog_file="");
void sync_config(std::string http_url, const VendorMap vendors);
bool sync_resources(std::string http_url, std::map<std::string, Resource> &resources, bool check_patch = false, std::string current_version="", std::string changelog_file="");
void remove_config_files(std::string vendor, std::string sub_path) const;
//compare_count means how many sub-versions in AA.BB.CC.DD need to be checked
bool get_valid_ota_version(Semver& app_version, Semver& current_version, Semver& cached_version, int compare_count) const;
void parse_ota_files(std::string ota_json, std::string& version, bool& force_upgrade, std::string& description) const;
bool sync_config(std::string http_url, const VendorMap vendors);
void sync_tooltip(std::string http_url, std::string language);
void sync_plugins(std::string http_url, std::string plugin_version);
void sync_printer_config(std::string http_url);
@@ -380,7 +388,7 @@ bool PresetUpdater::priv::extract_file(const fs::path &source_path, const fs::pa
// Remove leftover paritally downloaded files, if any.
void PresetUpdater::priv::prune_tmps() const
{
for (auto &dir_entry : boost::filesystem::directory_iterator(cache_path))
for (auto &dir_entry : fs::directory_iterator(cache_path))
if (is_plain_file(dir_entry) && dir_entry.path().extension() == TMP_EXTENSION) {
BOOST_LOG_TRIVIAL(debug) << "[QDT Updater]remove old cached files: " << dir_entry.path().string();
fs::remove(dir_entry.path());
@@ -489,8 +497,9 @@ void PresetUpdater::priv::parse_version_string(const std::string& body) const
//QDS: refine the Preset Updater logic
// Download vendor indices. Also download new bundles if an index indicates there's a new one available.
// Both are saved in cache.
void PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::string, Resource> &resources, bool check_patch, std::string current_version_str, std::string changelog_file)
bool PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::string, Resource> &resources, bool check_patch, std::string current_version_str, std::string changelog_file)
{
bool has_new_update = false;
std::map<std::string, Resource> resource_list;
BOOST_LOG_TRIVIAL(info) << boost::format("[QDT Updater]: sync_resources get preferred setting version for app version %1%, url: %2%, current_version_str %3%, check_patch %4%")%SLIC3R_APP_NAME%http_url%current_version_str%check_patch;
@@ -498,7 +507,7 @@ void PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
std::string query_params = "?";
bool first = true;
for (auto resource_it : resources) {
if (cancel) { return; }
if (cancel) { return false; }
auto resource_name = resource_it.first;
boost::to_lower(resource_name);
std::string query_resource = (boost::format("%1%=%2%")
@@ -550,7 +559,7 @@ void PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
}
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]: get type " << resource << ", version " << version << ", url " << url<<", force_update "<<force_upgrade;
resource_list.emplace(resource, Resource{version, description, url, force_upgrade});
resource_list.emplace(resource, Resource{version, description, url, "", force_upgrade});
}
}
} else {
@@ -568,7 +577,7 @@ void PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
.perform_sync();
for (auto & resource_it : resources) {
if (cancel) { return; }
if (cancel) { return false; }
auto resource = resource_it.second;
std::string resource_name = resource_it.first;
@@ -591,7 +600,7 @@ void PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
}
}
if (version_match && (current_version < online_version)) {
if (cancel) { return; }
if (cancel) { return false; }
// need to download the online files
fs::path cache_path(resource.cache_root);
@@ -602,25 +611,31 @@ void PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
BOOST_LOG_TRIVIAL(warning) << "[QDT Updater]download resource " << resource_name << " failed, url: " << online_url;
continue;
}
if (cancel) { return; }
if (cancel) { return false; }
// remove previous files before
if (resource.sub_caches.empty()) {
if (fs::exists(cache_path)) {
fs::remove_all(cache_path);
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]remove cache path " << cache_path.string();
}
} else {
for (auto sub : resource.sub_caches) {
if (fs::exists(cache_path / sub)) {
fs::remove_all(cache_path / sub);
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]remove cache path " << (cache_path / sub).string();
if (resource.vendor.empty()) {
if (resource.sub_caches.empty()) {
if (fs::exists(cache_path)) {
fs::remove_all(cache_path);
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]remove cache path " << cache_path.string();
}
} else {
for (auto sub : resource.sub_caches) {
if (fs::exists(cache_path / sub)) {
fs::remove_all(cache_path / sub);
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]remove cache path " << (cache_path / sub).string();
}
}
}
}
else {
remove_config_files(resource.vendor, PRESET_SUBPATH);
}
// extract the file downloaded
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]start to unzip the downloaded file " << cache_file_path << " to "<<cache_path;
fs::create_directories(cache_path);
if (!fs::exists(cache_path))
fs::create_directories(cache_path);
if (!extract_file(cache_file_path, cache_path)) {
BOOST_LOG_TRIVIAL(warning) << "[QDT Updater]extract resource " << resource_it.first << " failed, path: " << cache_file_path;
continue;
@@ -644,6 +659,8 @@ void PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
c.open(changelog_file, std::ios::out | std::ios::trunc);
c << std::setw(4) << j << std::endl;
c.close();
has_new_update = true;
}
catch(std::exception &err) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": save to "<<changelog_file<<" got a generic exception, reason = " << err.what();
@@ -655,22 +672,163 @@ void PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
BOOST_LOG_TRIVIAL(warning) << boost::format("[QDT Updater]: online version=%1%, current_version=%2%, no need to download") % online_version.to_string() % current_version.to_string();
}
}
return has_new_update;
}
bool PresetUpdater::priv::get_valid_ota_version(Semver& app_version, Semver& current_version, Semver& cached_version, int compare_count) const
{
bool valid = false;
int app_patch_cc = app_version.patch()/100;
int cached_patch_cc = cached_version.patch()/100;
int curent_patch_cc = current_version.patch()/100;
int app_patch_dd = app_version.patch()%100;
int cached_patch_dd = cached_version.patch() % 100;
int curent_patch_dd = current_version.patch()%100;
if (compare_count <= 1) {
if ((cached_version.maj() == app_version.maj())
&& ((cached_version.min() > current_version.min())
|| ((cached_version.min() == current_version.min()) && (cached_patch_cc > curent_patch_cc))
|| ((cached_version.min() == current_version.min()) && (cached_patch_cc == curent_patch_cc) && (cached_patch_dd > curent_patch_dd) )))
valid = true;
}
else if (compare_count == 2) {
if ((cached_version.maj() == app_version.maj()) && (cached_version.min() == app_version.min())
&& ((cached_patch_cc > curent_patch_cc)
|| ((cached_patch_cc == curent_patch_cc) && (cached_patch_dd > curent_patch_dd) )))
valid = true;
}
else if (compare_count == 3) {
if ((cached_version.maj() == app_version.maj()) && (cached_version.min() == app_version.min()) && (cached_patch_cc == app_patch_cc)
&& (cached_patch_dd > curent_patch_dd))
valid = true;
}
return valid;
}
void PresetUpdater::priv::parse_ota_files(std::string ota_json, std::string& version, bool& force_upgrade, std::string& description) const
{
version.clear();
if (fs::exists(ota_json)) {
try {
boost::nowide::ifstream ifs(ota_json);
json j;
ifs >> j;
if (j.contains("version"))
version = j["version"];
if (j.contains("force"))
force_upgrade = j["force"];
if (j.contains("description"))
description = j["description"];
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": ota_json %1%, version %2%, force %3%, description %4%")%ota_json %version %force_upgrade %description;
}
catch(nlohmann::detail::parse_error &err) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<<ota_json<<" got a nlohmann::detail::parse_error, reason = " << err.what();
}
}
return;
}
void PresetUpdater::priv::remove_config_files(std::string vendor, std::string sub_path) const
{
fs::path cache_folder = sub_path.empty()?cache_path : (cache_path / sub_path);
fs::path vendor_folder = sub_path.empty()?(cache_path / vendor): (cache_path / sub_path / vendor);
std::string vendor_ota_json = cache_folder.string() + "/"+vendor+".changelog";
std::string vendor_json = cache_folder.string() + "/"+vendor+".json";
if (fs::exists(vendor_ota_json)) {
try {
fs::remove(vendor_ota_json);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing vendor ota json: " << vendor_ota_json;
}
}
if (fs::exists(vendor_json)) {
try {
fs::remove(vendor_json);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing vendor json: " << vendor_json;
}
}
if (fs::exists(vendor_folder)) {
try {
fs::remove_all(vendor_folder);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing the vendor directory: " << vendor_folder.string();
}
}
return;
}
//QDS: refine the Preset Updater logic
// Download vendor indices. Also download new bundles if an index indicates there's a new one available.
// Both are saved in cache.
void PresetUpdater::priv::sync_config(std::string http_url, const VendorMap vendors)
bool PresetUpdater::priv::sync_config(std::string http_url, const VendorMap vendors)
{
std::map<std::string, std::pair<Semver, std::string>> vendor_list;
std::map<std::string, std::string> vendor_descriptions;
bool has_new_config = false;
//std::map<std::string, std::pair<Semver, std::string>> vendor_list;
//std::map<std::string, std::string> vendor_descriptions;
BOOST_LOG_TRIVIAL(info) << boost::format("[QDT Updater]: sync_config Syncing configuration enter");
if (!enabled_config_update) { return; }
if (!enabled_config_update) { return has_new_config; }
BOOST_LOG_TRIVIAL(info) << boost::format("[QDT Updater]: sync_config get preferred setting version for app version %1%, http_url: %2%")%SLIC3R_VERSION%http_url;
auto cache_folder = cache_path / PRESET_SUBPATH;
std::string curr_app_version = SLIC3R_VERSION;
std::string using_app_version = curr_app_version.substr(0, 6) + "00.00";
for (auto vendor_it :vendors) {
const VendorProfile& vendor_profile = vendor_it.second;
std::string vendor_name = vendor_profile.id, vendor = vendor_profile.id;
boost::to_lower(vendor_name);
if (vendor != PresetBundle::QDT_BUNDLE)
continue;
std::string vendor_ota_json = cache_folder.string() + "/"+vendor+".changelog";
std::string vendor_resource_json = vendor_path.string() + "/"+vendor+".json";
Semver current_preset_semver = get_version_from_json(vendor_resource_json);
std::string cached_version, description;
bool force = false, remove_previous = true, valid_version = false;
//check previous cached config files, and delete unused
parse_ota_files(vendor_ota_json, cached_version, force, description);
if (!cached_version.empty()) {
Semver app_semver = curr_app_version;
Semver cached_semver = cached_version;
valid_version = get_valid_ota_version(app_semver, current_preset_semver, cached_semver, 2);
if (valid_version) {
remove_previous = false;
current_preset_semver = cached_semver;
has_new_config = true;
}
}
//remove previous config files
if (remove_previous)
remove_config_files(vendor, PRESET_SUBPATH);
//check online versions
try {
std::map<std::string, Resource> resources
{
{"slicer/settings/"+vendor_name, { using_app_version, "", "", vendor, false, cache_folder.string()}}
};
has_new_config |= sync_resources(http_url, resources, false, current_preset_semver.to_string(), vendor+".changelog");
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(warning) << format("[QDT Updater] sync_plugins: %1%", e.what());
}
}
#if 0
std::string app_version = SLIC3R_VERSION;
std::string query_version = app_version.substr(0, 6) + "00.00";
std::string query_params = "?";
@@ -721,6 +879,7 @@ void PresetUpdater::priv::sync_config(std::string http_url, const VendorMap vend
std::string type;
std::string vendor;
std::string description;
bool force_upgrade = false;
for (auto sub_iter = iter.value().begin(); sub_iter != iter.value().end(); sub_iter++) {
if (boost::iequals(sub_iter.key(),"type")) {
type = sub_iter.value();
@@ -735,6 +894,10 @@ void PresetUpdater::priv::sync_config(std::string http_url, const VendorMap vend
else if (boost::iequals(sub_iter.key(),"url")) {
url = sub_iter.value();
}
else if (boost::iequals(sub_iter.key(), "force_update")) {
force_upgrade = sub_iter.value();
}
}
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]: get type "<< type <<", version "<<version.to_string()<<", url " << url;
@@ -868,6 +1031,8 @@ void PresetUpdater::priv::sync_config(std::string http_url, const VendorMap vend
}
}
}
#endif
return has_new_config;
}
void PresetUpdater::priv::sync_tooltip(std::string http_url, std::string language)
@@ -884,8 +1049,8 @@ void PresetUpdater::priv::sync_tooltip(std::string http_url, std::string languag
} catch (...) {}
std::map<std::string, Resource> resources
{
{"slicer/tooltip/common", { common_version, "", "", false, (cache_root / "common").string() }},
{"slicer/tooltip/" + language, { language_version, "", "", false, (cache_root / language).string() }}
{"slicer/tooltip/common", { common_version, "", "", "", false, (cache_root / "common").string() }},
{"slicer/tooltip/" + language, { language_version, "", "", "", false, (cache_root / language).string() }}
};
sync_resources(http_url, resources);
for (auto &r : resources) {
@@ -903,9 +1068,7 @@ void PresetUpdater::priv::sync_tooltip(std::string http_url, std::string languag
// return true means there are plugins files
bool PresetUpdater::priv::get_cached_plugins_version(std::string& cached_version, bool &force)
{
std::string data_dir_str = data_dir();
boost::filesystem::path data_dir_path(data_dir_str);
auto cache_folder = data_dir_path / "ota";
auto cache_folder = cache_path / "plugins";
std::string network_library, player_library, live555_library;
bool has_plugins = false;
@@ -924,28 +1087,14 @@ bool PresetUpdater::priv::get_cached_plugins_version(std::string& cached_version
#endif
std::string changelog_file = cache_folder.string() + "/network_plugins.json";
if (boost::filesystem::exists(network_library)
&& boost::filesystem::exists(player_library)
&& boost::filesystem::exists(live555_library)
&& boost::filesystem::exists(changelog_file))
if (fs::exists(network_library)
&& fs::exists(player_library)
&& fs::exists(live555_library)
&& fs::exists(changelog_file))
{
has_plugins = true;
try {
boost::nowide::ifstream ifs(changelog_file);
json j;
ifs >> j;
if (j.contains("version"))
cached_version = j["version"];
if (j.contains("force"))
force = j["force"];
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": cached_version = "<<cached_version<<", force = " << force;
}
catch(nlohmann::detail::parse_error &err) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<<changelog_file<<" got a nlohmann::detail::parse_error, reason = " << err.what();
//throw ConfigurationError(format("Failed loading json file \"%1%\": %2%", file_path, err.what()));
}
std::string description;
parse_ota_files(changelog_file, cached_version, force, description);
}
return has_plugins;
@@ -959,96 +1108,38 @@ void PresetUpdater::priv::sync_plugins(std::string http_url, std::string plugin_
}
std::string curr_version = SLIC3R_VERSION;
std::string using_version = curr_version.substr(0, 9) + "00";
auto cache_plugin_folder = cache_path / PLUGINS_SUBPATH;
std::string cached_version;
bool force_upgrade = false;
get_cached_plugins_version(cached_version, force_upgrade);
if (!cached_version.empty()) {
bool need_delete_cache = false;
bool need_delete_cache = true;
Semver current_semver = curr_version;
Semver cached_semver = cached_version;
Semver current_plugin_semver = plugin_version;
int curent_patch_cc = current_semver.patch()/100;
int cached_patch_cc = cached_semver.patch()/100;
int curent_patch_dd = current_semver.patch()%100;
int curent_plugin_patch_dd = current_plugin_semver.patch()%100;
int cached_patch_dd = cached_semver.patch()%100;
if ((cached_semver.maj() != current_semver.maj())
|| (cached_semver.min() != current_semver.min())
|| (curent_patch_cc != cached_patch_cc))
{
need_delete_cache = true;
BOOST_LOG_TRIVIAL(info) << boost::format("cached plugins version %1% not match with current %2%")%cached_version%curr_version;
}
else if (cached_patch_dd <= curent_plugin_patch_dd) {
need_delete_cache = true;
BOOST_LOG_TRIVIAL(info) << boost::format("cached plugins version %1% not newer than current %2%")%cached_version%curr_version;
}
else {
bool valid_version = get_valid_ota_version(current_semver, current_plugin_semver, cached_semver, 3);
if (valid_version) {
BOOST_LOG_TRIVIAL(info) << boost::format("cached plugins version %1% newer than current %2%")%cached_version%curr_version;
plugin_version = cached_version;
need_delete_cache = false;
}
if (need_delete_cache) {
std::string data_dir_str = data_dir();
boost::filesystem::path data_dir_path(data_dir_str);
auto cache_folder = data_dir_path / "ota";
#if defined(_MSC_VER) || defined(_WIN32)
auto network_library = cache_folder / "qidi_networking.dll";
auto player_library = cache_folder / "QIDISource.dll";
auto live555_library = cache_folder / "live555.dll";
#elif defined(__WXMAC__)
auto network_library = cache_folder / "libqidi_networking.dylib";
auto player_library = cache_folder / "libQIDISource.dylib";
auto live555_library = cache_folder / "liblive555.dylib";
#else
auto network_library = cache_folder / "libqidi_networking.so";
auto player_library = cache_folder / "libQIDISource.so";
auto live555_library = cache_folder / "liblive555.so";
#endif
auto changelog_file = cache_folder / "network_plugins.json";
if (boost::filesystem::exists(network_library))
if (fs::exists(cache_plugin_folder))
{
BOOST_LOG_TRIVIAL(info) << "[remove_old_networking_plugins] remove the file "<<network_library.string();
BOOST_LOG_TRIVIAL(info) << "[remove_old_networking_plugins] remove the plugins directory "<<cache_plugin_folder.string();
try {
fs::remove(network_library);
fs::remove_all(cache_plugin_folder);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing the plugins file " << network_library.string();
BOOST_LOG_TRIVIAL(error) << "Failed removing the plugins file " << cache_plugin_folder.string();
}
}
if (boost::filesystem::exists(player_library))
{
BOOST_LOG_TRIVIAL(info) << "[remove_old_networking_plugins] remove the file "<<player_library.string();
try {
fs::remove(player_library);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing the plugins file " << player_library.string();
}
}
if (boost::filesystem::exists(live555_library))
{
BOOST_LOG_TRIVIAL(info) << "[remove_old_networking_plugins] remove the file " << live555_library.string();
try {
fs::remove(live555_library);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing the plugins file " << live555_library.string();
}
}
if (boost::filesystem::exists(changelog_file))
{
BOOST_LOG_TRIVIAL(info) << "[remove_old_networking_plugins] remove the file "<<changelog_file.string();
try {
fs::remove(changelog_file);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing the plugins file " << changelog_file.string();
}
//create this directory again
if (!fs::exists(cache_plugin_folder)) {
fs::create_directory(cache_plugin_folder);
}
}
}
@@ -1056,7 +1147,7 @@ void PresetUpdater::priv::sync_plugins(std::string http_url, std::string plugin_
try {
std::map<std::string, Resource> resources
{
{"slicer/plugins/cloud", { using_version, "", "", false, cache_path.string(), {"plugins"}}}
{"slicer/plugins/cloud", { using_version, "", "", "", false, cache_plugin_folder.string()}}
};
sync_resources(http_url, resources, true, plugin_version, "network_plugins.json");
}
@@ -1086,7 +1177,7 @@ void PresetUpdater::priv::sync_printer_config(std::string http_url)
std::string cached_version;
std::string data_dir_str = data_dir();
boost::filesystem::path data_dir_path(data_dir_str);
fs::path data_dir_path(data_dir_str);
auto config_folder = data_dir_path / "printers";
auto cache_folder = data_dir_path / "ota" / "printers";
@@ -1104,28 +1195,32 @@ void PresetUpdater::priv::sync_printer_config(std::string http_url)
} catch (...) {}
if (!cached_version.empty()) {
bool need_delete_cache = false;
Semver current_semver = curr_version;
Semver cached_semver = cached_version;
Semver current_semver = curr_version;
Semver cached_semver = cached_version;
if ((cached_semver.maj() != current_semver.maj()) || (cached_semver.min() != current_semver.min())) {
need_delete_cache = true;
BOOST_LOG_TRIVIAL(info) << boost::format("cached printer config version %1% not match with current %2%") % cached_version % curr_version;
} else if (cached_semver.patch() <= current_semver.patch()) {
}
else if (cached_semver.patch() <= current_semver.patch()) {
need_delete_cache = true;
BOOST_LOG_TRIVIAL(info) << boost::format("cached printer config version %1% not newer than current %2%") % cached_version % curr_version;
} else {
}
else {
using_version = cached_version;
}
if (need_delete_cache) {
boost::system::error_code ec;
boost::filesystem::remove_all(cache_folder, ec);
cached_version = curr_version;
fs::remove_all(cache_folder, ec);
cached_version = curr_version;
}
}
else
cached_version = curr_version;
try {
std::map<std::string, Resource> resources{{"slicer/printer/qdt", {using_version, "", "", false, cache_folder.string()}}};
std::map<std::string, Resource> resources{{"slicer/printer/qdt", {using_version, "", "", "", false, cache_folder.string()}}};
sync_resources(http_url, resources, false, cached_version, "printer.json");
} catch (std::exception &e) {
BOOST_LOG_TRIVIAL(warning) << format("[QDT Updater] sync_printer_config: %1%", e.what());
@@ -1185,7 +1280,7 @@ void PresetUpdater::priv::check_installed_vendor_profiles() const
//QDS: refine the init check logic
std::vector<std::string> bundles;
for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_path)) {
for (auto &dir_entry : fs::directory_iterator(rsrc_path)) {
const auto &path = dir_entry.path();
std::string file_path = path.string();
if (is_json_file(file_path)) {
@@ -1214,6 +1309,7 @@ void PresetUpdater::priv::check_installed_vendor_profiles() const
fs::remove_all(path_of_vendor);
}
}
//y
else if ((vendor_name == PresetBundle::QDT_BUNDLE) || (enabled_vendors.find(vendor_name) != enabled_vendors.end())) {//if vendor has no file, copy it from resource for QDT
bundles.push_back(vendor_name);
}
@@ -1234,8 +1330,8 @@ void PresetUpdater::priv::check_installed_vendor_profiles() const
Updates PresetUpdater::priv::get_printer_config_updates(bool update) const
{
std::string data_dir_str = data_dir();
boost::filesystem::path data_dir_path(data_dir_str);
boost::filesystem::path resc_dir_path(resources_dir());
fs::path data_dir_path(data_dir_str);
fs::path resc_dir_path(resources_dir());
auto config_folder = data_dir_path / "printers";
auto resc_folder = (update ? cache_path : resc_dir_path) / "printers";
std::string curr_version;
@@ -1288,67 +1384,57 @@ Updates PresetUpdater::priv::get_printer_config_updates(bool update) const
//QDS: refine the Preset Updater logic
Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version) const
{
Updates updates;
Updates updates;
auto cache_folder = cache_path / PRESET_SUBPATH;
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]:Checking for cached configuration updates...";
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]:Checking for cached configuration updates...";
for (auto &dir_entry : boost::filesystem::directory_iterator(cache_path)) {
const auto &path = dir_entry.path();
std::string file_path = path.string();
if (is_json_file(file_path)) {
const auto path_in_vendor = vendor_path / path.filename();
std::string vendor_name = path.filename().string();
// Remove the .json suffix.
vendor_name.erase(vendor_name.size() - 5);
auto print_in_cache = (cache_path / vendor_name / PRESET_PRINT_NAME);
auto filament_in_cache = (cache_path / vendor_name / PRESET_FILAMENT_NAME);
auto machine_in_cache = (cache_path / vendor_name / PRESET_PRINTER_NAME);
//remove previous old datas
remove_config_files("QDT", std::string());
if (( fs::exists(path_in_vendor))
&&( fs::exists(print_in_cache))
&&( fs::exists(filament_in_cache))
&&( fs::exists(machine_in_cache))) {
Semver vendor_ver = get_version_from_json(path_in_vendor.string());
if (fs::exists(cache_folder)) {
for (auto& dir_entry : fs::directory_iterator(cache_folder)) {
const auto& path = dir_entry.path();
std::string file_path = path.string();
if (is_json_file(file_path)) {
const auto path_in_vendor = vendor_path / path.filename();
std::string vendor_name = path.filename().string(), cached_version, description;
// Remove the .json suffix.
vendor_name.erase(vendor_name.size() - 5);
auto print_in_cache = (cache_folder / vendor_name / PRESET_PRINT_NAME);
auto filament_in_cache = (cache_folder / vendor_name / PRESET_FILAMENT_NAME);
auto machine_in_cache = (cache_folder / vendor_name / PRESET_PRINTER_NAME);
std::map<std::string, std::string> key_values;
std::vector<std::string> keys(3);
Semver cache_ver;
keys[0] = QDT_JSON_KEY_VERSION;
keys[1] = QDT_JSON_KEY_DESCRIPTION;
keys[2] = QDT_JSON_KEY_FORCE_UPDATE;
get_values_from_json(file_path, keys, key_values);
std::string description = key_values[QDT_JSON_KEY_DESCRIPTION];
bool force_update = false;
if (key_values.find(QDT_JSON_KEY_FORCE_UPDATE) != key_values.end())
force_update = (key_values[QDT_JSON_KEY_FORCE_UPDATE] == "1")?true:false;
auto config_version = Semver::parse(key_values[QDT_JSON_KEY_VERSION]);
if (config_version)
cache_ver = *config_version;
std::string changelog_file = (cache_folder / (vendor_name + ".changelog")).string();
bool force_update;
std::string changelog;
std::string changelog_file = (cache_path / (vendor_name + ".changelog")).string();
boost::nowide::ifstream ifs(changelog_file);
if (ifs) {
std::ostringstream oss;
oss<< ifs.rdbuf();
changelog = oss.str();
//ifs>>changelog;
ifs.close();
}
if ((fs::exists(path_in_vendor))
&& (fs::exists(print_in_cache))
&& (fs::exists(filament_in_cache))
&& (fs::exists(machine_in_cache))) {
bool version_match = ((vendor_ver.maj() == cache_ver.maj()) && (vendor_ver.min() == cache_ver.min()));
if (version_match && (vendor_ver < cache_ver)) {
Semver app_ver = *Semver::parse(SLIC3R_VERSION);
if (cache_ver.maj() == app_ver.maj()){
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]:need to update settings from "<<vendor_ver.to_string()<<" to newer version "<<cache_ver.to_string() <<", app version "<<SLIC3R_VERSION;
Version version;
version.config_version = cache_ver;
version.comment = description;
parse_ota_files(changelog_file, cached_version, force_update, description);
if (!cached_version.empty()) {
BOOST_LOG_TRIVIAL(info) << boost::format("[QDT Updater] found new presets of vendor: %1%, version %2%, force_upgrade %3%") % vendor_name % cached_version % force_update;
std::string app_version = SLIC3R_VERSION;
Semver app_semver = app_version;
Semver cached_semver = cached_version;
Semver current_preset_semver = get_version_from_json(path_in_vendor.string());
updates.updates.emplace_back(std::move(file_path), std::move(path_in_vendor.string()), std::move(version), vendor_name, changelog, "", force_update, false);
bool valid_version = get_valid_ota_version(app_semver, current_preset_semver, cached_semver, 2);
//QDS: add directory support
updates.updates.emplace_back(cache_path / vendor_name, vendor_path / vendor_name, Version(), vendor_name, "", "", force_update, true);
if (valid_version) {
BOOST_LOG_TRIVIAL(info) << boost::format("[QDT Updater] need to update vendor: %1%'s settings from version %2% to newer version %3%, force_upgrade %4%")
% vendor_name % current_preset_semver.to_string() % cached_semver.to_string() % force_update;
Version version;
version.config_version = cached_semver;
//version.comment = description;
updates.updates.emplace_back(std::move(file_path), std::move(path_in_vendor.string()), std::move(version), vendor_name, description, "", force_update, false);
//QDS: add directory support
updates.updates.emplace_back(cache_folder / vendor_name, vendor_path / vendor_name, Version(), vendor_name, "", "", force_update, true);
}
}
}
}
@@ -1444,38 +1530,41 @@ PresetUpdater::~PresetUpdater()
//QDS: refine the preset updater logic
void PresetUpdater::sync(std::string http_url, std::string language, std::string plugin_version, PresetBundle *preset_bundle)
{
//p->set_download_prefs(GUI::wxGetApp().app_config);
if (!p->enabled_version_check && !p->enabled_config_update) { return; }
//p->set_download_prefs(GUI::wxGetApp().app_config);
if (!p->enabled_version_check && !p->enabled_config_update) { return; }
// Copy the whole vendors data for use in the background thread
// Unfortunatelly as of C++11, it needs to be copied again
// into the closure (but perhaps the compiler can elide this).
// Copy the whole vendors data for use in the background thread
// Unfortunatelly as of C++11, it needs to be copied again
// into the closure (but perhaps the compiler can elide this).
VendorMap vendors = preset_bundle ? preset_bundle->vendors : VendorMap{};
p->thread = std::thread([this, vendors, http_url, language, plugin_version]() {
this->p->prune_tmps();
if (p->cancel)
return;
this->p->sync_version();
if (p->cancel)
return;
p->thread = std::thread([this, vendors, http_url, language, plugin_version]() {
this->p->prune_tmps();
if (p->cancel)
return;
//not used
//this->p->sync_version();
//if (p->cancel)
// return;
if (!vendors.empty()) {
this->p->sync_config(http_url, std::move(vendors));
if (p->cancel)
return;
GUI::wxGetApp().CallAfter([] {
GUI::wxGetApp().check_config_updates_from_updater();
});
bool has_new_config = this->p->sync_config(http_url, std::move(vendors));
if (p->cancel)
return;
if (has_new_config) {
GUI::wxGetApp().CallAfter([] {
GUI::wxGetApp().check_config_updates_from_updater();
});
}
}
if (p->cancel)
return;
if (p->cancel)
return;
this->p->sync_plugins(http_url, plugin_version);
this->p->sync_printer_config(http_url);
//if (p->cancel)
// return;
//remove the tooltip currently
//this->p->sync_tooltip(http_url, language);
});
//if (p->cancel)
// return;
//remove the tooltip currently
//this->p->sync_tooltip(http_url, language);
});
}
void PresetUpdater::slic3r_update_notify()

View File

@@ -34,4 +34,16 @@ namespace ProfileDescrption {
const std::string PROFILE_DESCRIPTION_26 = _L("Compared with the default profile of a 0.8 mm nozzle, it has a slightly smaller layer height, and results in slightly less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.");
const std::string PROFILE_DESCRIPTION_27 = _L("Compared with the default profile of a 0.8 mm nozzle, it has a smaller layer height, and results in less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.");
const std::string PROFILE_DESCRIPTION_28 = _L("This is neither a commonly used filament, nor one of QIDI filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.");
const std::string PROFILE_DESCRIPTION_29 = _L("When printing this filament, there's a risk of warping and low layer adhesion strength. To get better results, please refer to this wiki: Printing Tips for High Temp / Engineering materials.");
const std::string PROFILE_DESCRIPTION_30 = _L("When printing this filament, there's a risk of nozzle clogging, oozing, warping and low layer adhesion strength. To get better results, please refer to this wiki: Printing Tips for High Temp / Engineering materials.");
const std::string PROFILE_DESCRIPTION_31 = _L("To get better transparent or translucent results with the corresponding filament, please refer to this wiki: Printing tips for transparent PETG.");
const std::string PROFILE_DESCRIPTION_32 = _L("To make the prints get higher gloss, please dry the filament before use, and set the outer wall speed to be 40 to 60 mm/s when slicing.");
const std::string PROFILE_DESCRIPTION_33 = _L("This filament is only used to print models with a low density usually, and some special parameters are required. To get better printing quality, please refer to this wiki: Instructions for printing RC model with foaming PLA (PLA Aero).");
const std::string PROFILE_DESCRIPTION_34 = _L("This filament is only used to print models with a low density usually, and some special parameters are required. To get better printing quality, please refer to this wiki: ASA Aero Printing Guide.");
const std::string PROFILE_DESCRIPTION_35 = _L("This filament is too soft and not compatible with the AMS. Printing it is of many requirements, and to get better printing quality, please refer to this wiki: TPU printing guide.");
const std::string PROFILE_DESCRIPTION_36 = _L("This filament has high enough hardness (about 67D) and is compatible with the AMS. Printing it is of many requirements, and to get better printing quality, please refer to this wiki: TPU printing guide.");
const std::string PROFILE_DESCRIPTION_37 = _L("If you are to print a kind of soft TPU, please don't slice with this profile, and it is only for TPU that has high enough hardness (not less than 55D) and is compatible with the AMS. To get better printing quality, please refer to this wiki: TPU printing guide.");
const std::string PROFILE_DESCRIPTION_38 = _L("This is a water-soluble support filament, and usually it is only for the support structure and not for the model body. Printing this filament is of many requirements, and to get better printing quality, please refer to this wiki: PVA Printing Guide.");
const std::string PROFILE_DESCRIPTION_39 = _L("This is a non-water-soluble support filament, and usually it is only for the support structure and not for the model body. To get better printing quality, please refer to this wiki: Printing Tips for Support Filament and Support Function.");
const std::string PROFILE_DESCRIPTION_40 = _L("The generic presets are conservatively tuned for compatibility with a wider range of filaments. For higher printing quality and speeds, please use QIDI filaments with QIDI presets.");
}

View File

@@ -0,0 +1,391 @@
#include "RaycastManager.hpp"
#include <utility>
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/CameraUtils.hpp"
using namespace Slic3r::GUI;
namespace{
using namespace Slic3r;
void actualize(RaycastManager::Meshes &meshes, const ModelVolumePtrs &volumes, const RaycastManager::ISkip *skip, RaycastManager::Meshes *input = nullptr);
const sla::IndexedMesh * get_mesh(const RaycastManager::Meshes &meshes, size_t volume_id);
RaycastManager::TrKey create_key(const ModelVolume& volume, const ModelInstance& instance){
return std::make_pair(instance.id().id, volume.id().id); }
RaycastManager::TrItems::iterator find(RaycastManager::TrItems &items, const RaycastManager::TrKey &key);
RaycastManager::TrItems::const_iterator find(const RaycastManager::TrItems &items, const RaycastManager::TrKey &key);
bool is_lower_key(const RaycastManager::TrKey &k1, const RaycastManager::TrKey &k2) {
return k1.first < k2.first || (k1.first == k2.first && k1.second < k2.second); }
bool is_lower(const RaycastManager::TrItem &i1, const RaycastManager::TrItem &i2) {
return is_lower_key(i1.first, i2.first); };
template<typename VecType> inline void erase(std::vector<VecType> &vec, const std::vector<bool> &flags);
}
void RaycastManager::actualize(const ModelObject &object, const ISkip *skip, Meshes *meshes)
{
// actualize MeshRaycaster
::actualize(m_meshes, object.volumes, skip, meshes);
// check if inscance was removed
std::vector<bool> removed_transf(m_transformations.size(), {true});
bool need_sort = false;
// actualize transformation matrices
for (const ModelVolume *volume : object.volumes) {
if (skip != nullptr && skip->skip(volume->id().id)) continue;
const Transform3d &volume_tr = volume->get_matrix();
for (const ModelInstance *instance : object.instances) {
const Transform3d &instrance_tr = instance->get_matrix();
Transform3d transformation = instrance_tr * volume_tr;
TrKey key = ::create_key(*volume, *instance);
auto item = ::find(m_transformations, key);
if (item != m_transformations.end()) {
// actualize transformation all the time
item->second = transformation;
size_t index = item - m_transformations.begin();
removed_transf[index] = false;
} else {
// add new transformation
m_transformations.emplace_back(key, transformation);
need_sort = true;
}
}
}
// clean other transformation
::erase(m_transformations, removed_transf);
if (need_sort)
std::sort(m_transformations.begin(), m_transformations.end(), ::is_lower);
}
void RaycastManager::actualize(const ModelInstance &instance, const ISkip *skip, Meshes *meshes)
{
const ModelVolumePtrs &volumes = instance.get_object()->volumes;
// actualize MeshRaycaster
::actualize(m_meshes, volumes, skip, meshes);
// check if inscance was removed
std::vector<bool> removed_transf(m_transformations.size(), {true});
bool need_sort = false;
// actualize transformation matrices
for (const ModelVolume *volume : volumes) {
if (skip != nullptr && skip->skip(volume->id().id))
continue;
const Transform3d &volume_tr = volume->get_matrix();
const Transform3d &instrance_tr = instance.get_matrix();
Transform3d transformation = instrance_tr * volume_tr;
TrKey key = ::create_key(*volume, instance);
auto item = ::find(m_transformations, key);
if (item != m_transformations.end()) {
// actualize transformation all the time
item->second = transformation;
size_t index = item - m_transformations.begin();
removed_transf[index] = false;
} else {
// add new transformation
m_transformations.emplace_back(key, transformation);
need_sort = true;
}
}
// clean other transformation
::erase(m_transformations, removed_transf);
if (need_sort)
std::sort(m_transformations.begin(), m_transformations.end(), ::is_lower);
}
std::optional<RaycastManager::Hit> RaycastManager::first_hit(const Vec3d& point, const Vec3d& direction, const ISkip *skip) const
{
// Improve: it is not neccessaru to use AABBMesh and calc normal for every hit
// Results
const sla::IndexedMesh *hit_mesh = nullptr;
double hit_squared_distance = 0.;
int hit_face = -1;
Vec3d hit_world;
const Transform3d *hit_tramsformation = nullptr;
const TrKey *hit_key = nullptr;
for (const auto &[key, transformation]: m_transformations) {
size_t volume_id = key.second;
if (skip != nullptr && skip->skip(volume_id))
continue;
const sla::IndexedMesh *mesh = ::get_mesh(m_meshes, volume_id);
if (mesh == nullptr) continue;
Transform3d inv = transformation.inverse();
// transform input into mesh world
Vec3d point_ = inv * point;
Vec3d direction_= inv.linear() * direction;
std::vector<sla::IndexedMesh::hit_result> hits = mesh->query_ray_hits(point_, direction_);
if (hits.empty()) continue; // no intersection found
const sla::IndexedMesh::hit_result &hit = hits.front();
// convert to world
Vec3d world = transformation * hit.position();
double squared_distance = (point - world).squaredNorm();
if (hit_mesh != nullptr &&
hit_squared_distance < squared_distance)
continue; // exist closer one
hit_mesh = mesh;
hit_squared_distance = squared_distance;
hit_face = hit.face();
hit_world = world;
hit_tramsformation = &transformation;
hit_key = &key;
}
if (hit_mesh == nullptr)
return {};
// Calculate normal from transformed triangle
// NOTE: Anisotropic transformation of normal is not perpendiculat to triangle
const Vec3i32 tri = hit_mesh->indices(hit_face);
std::array<Vec3d,3> pts;
auto tr = hit_tramsformation->linear();
for (int i = 0; i < 3; ++i)
pts[i] = tr * hit_mesh->vertices(tri[i]).cast<double>();
Vec3d normal_world = (pts[1] - pts[0]).cross(pts[2] - pts[1]);
if (has_reflection(*hit_tramsformation))
normal_world *= -1;
normal_world.normalize();
SurfacePoint<double> point_world{hit_world, normal_world};
return RaycastManager::Hit{point_world, *hit_key, hit_squared_distance};
}
std::optional<RaycastManager::Hit> RaycastManager::closest_hit(const Vec3d &point, const Vec3d &direction, const ISkip *skip) const
{
std::optional<Hit> closest;
for (const auto &[key, transformation] : m_transformations) {
size_t volume_id = key.second;
if (skip != nullptr && skip->skip(volume_id)) continue;
const sla::IndexedMesh *mesh = ::get_mesh(m_meshes, volume_id);
if (mesh == nullptr) continue;
Transform3d tr_inv = transformation.inverse();
Vec3d mesh_point = tr_inv * point;
Vec3d mesh_direction = tr_inv.linear() * direction;
// Need for detect that actual point position is on correct place
Vec3d point_positive = mesh_point - mesh_direction;
Vec3d point_negative = mesh_point + mesh_direction;
// Throw ray to both directions of ray
std::vector<sla::IndexedMesh::hit_result> hits = mesh->query_ray_hits(point_positive, mesh_direction);
std::vector<sla::IndexedMesh::hit_result> hits_neg = mesh->query_ray_hits(point_negative, -mesh_direction);
hits.insert(hits.end(), std::make_move_iterator(hits_neg.begin()), std::make_move_iterator(hits_neg.end()));
for (const sla::IndexedMesh::hit_result &hit : hits) {
Vec3d diff = mesh_point - hit.position();
double squared_distance = diff.squaredNorm();
if (closest.has_value() &&
closest->squared_distance < squared_distance)
continue;
closest = Hit{{hit.position(), hit.normal()}, key, squared_distance};
}
}
return closest;
}
std::optional<RaycastManager::ClosePoint> RaycastManager::closest(const Vec3d &point, const ISkip *skip) const
{
std::optional<ClosePoint> closest;
for (const auto &[key, transformation] : m_transformations) {
size_t volume_id = key.second;
if (skip != nullptr && skip->skip(volume_id))
continue;
const sla::IndexedMesh *mesh = ::get_mesh(m_meshes, volume_id);
if (mesh == nullptr) continue;
Transform3d tr_inv = transformation.inverse();
Vec3d mesh_point = tr_inv * point;
int face_idx = 0;
Vec3d closest_point;
Vec3d pointd = point.cast<double>();
mesh->squared_distance(pointd, face_idx, closest_point);
double squared_distance = (mesh_point - closest_point).squaredNorm();
if (closest.has_value() && closest->squared_distance < squared_distance)
continue;
closest = ClosePoint{key, closest_point, squared_distance};
}
return closest;
}
Slic3r::Transform3d RaycastManager::get_transformation(const TrKey &tr_key) const {
auto tr = ::find(m_transformations, tr_key);
if (tr == m_transformations.end())
return Transform3d::Identity();
return tr->second;
}
void Slic3r::GUI::RaycastManager::clear() {
m_meshes.clear();
m_transformations.clear();
}
namespace {
void actualize(RaycastManager::Meshes &meshes, const ModelVolumePtrs &volumes, const RaycastManager::ISkip *skip, RaycastManager::Meshes* inputs)
{
// check if volume was removed
std::vector<bool> removed_meshes(meshes.size(), {true});
bool need_sort = false;
// actualize MeshRaycaster
for (const ModelVolume *volume : volumes) {
size_t oid = volume->id().id;
if (skip != nullptr && skip->skip(oid))
continue;
auto is_oid = [oid](const RaycastManager::Mesh &it) { return oid == it.first; };
if (auto item = std::find_if(meshes.begin(), meshes.end(), is_oid);
item != meshes.end()) {
size_t index = item - meshes.begin();
removed_meshes[index] = false;
continue;
}
// exist AABB in inputs ?
if (inputs != nullptr) {
auto input = std::find_if(inputs->begin(), inputs->end(), is_oid);
if (input != inputs->end()) {
meshes.emplace_back(std::move(*input));
need_sort = true;
continue;
}
}
// add new raycaster
bool calculate_epsilon = true;
auto mesh = std::make_unique<sla::IndexedMesh>(volume->mesh(), calculate_epsilon);
meshes.emplace_back(std::make_pair(oid, std::move(mesh)));
need_sort = true;
}
// clean other raycasters
erase(meshes, removed_meshes);
// All the time meshes must be sorted by volume id - for faster search
if (need_sort) {
auto is_lower = [](const RaycastManager::Mesh &m1, const RaycastManager::Mesh &m2) { return m1.first < m2.first; };
std::sort(meshes.begin(), meshes.end(), is_lower);
}
}
const Slic3r::sla::IndexedMesh *get_mesh(const RaycastManager::Meshes &meshes, size_t volume_id)
{
auto is_lower_index = [](const RaycastManager::Mesh &m, size_t i) { return m.first < i; };
auto it = std::lower_bound(meshes.begin(), meshes.end(), volume_id, is_lower_index);
if (it == meshes.end() || it->first != volume_id)
return nullptr;
return &(*(it->second));
}
RaycastManager::TrItems::iterator find(RaycastManager::TrItems &items, const RaycastManager::TrKey &key) {
auto fnc = [](const RaycastManager::TrItem &it, const RaycastManager::TrKey &l_key) { return is_lower_key(it.first, l_key); };
auto it = std::lower_bound(items.begin(), items.end(), key, fnc);
if (it != items.end() && it->first != key)
return items.end();
return it;
}
RaycastManager::TrItems::const_iterator find(const RaycastManager::TrItems &items, const RaycastManager::TrKey &key)
{
auto fnc = [](const RaycastManager::TrItem &it, const RaycastManager::TrKey &l_key) { return is_lower_key(it.first, l_key); };
auto it = std::lower_bound(items.begin(), items.end(), key, fnc);
if (it != items.end() && it->first != key)
return items.end();
return it;
}
template<typename VecType> inline void erase(std::vector<VecType> &vec, const std::vector<bool> &flags)
{
if (vec.size() < flags.size() || flags.empty())
return;
// reverse iteration over flags to erase indices from back to front.
for (int i = static_cast<int>(flags.size()) - 1; i >= 0; --i)
if (flags[i])
vec.erase(vec.begin() + i);
}
} // namespace
namespace Slic3r::GUI{
RaycastManager::Meshes create_meshes(GLCanvas3D &canvas, const RaycastManager::AllowVolumes &condition)
{
RaycastManager::Meshes meshes;//from
throw;
//std::map<GLVolume *, std::shared_ptr<PickRaycaster>> m_mesh_raycaster_map;//for text
/*
m_mesh_raycaster_map[v] = std::make_shared<PickRaycaster>(mesh, -1);
SceneRaycaster::EType type = SceneRaycaster::EType::Volume;
auto scene_casters = canvas.get_raycasters_for_picking(type);
if (scene_casters == nullptr)
return {};
const std::vector<std::shared_ptr<SceneRaycasterItem>> &casters = *scene_casters;
const GLVolumePtrs &gl_volumes = canvas.get_volumes().volumes;
const ModelObjectPtrs &objects = canvas.get_model()->objects;
for (const std::shared_ptr<SceneRaycasterItem> &caster : casters) {
int index = SceneRaycaster::decode_id(type, caster->get_id());
if (index < 0)
continue;
auto index_ = static_cast<size_t>(index);
if(index_ >= gl_volumes.size())
continue;
const GLVolume *gl_volume = gl_volumes[index_];
if (gl_volume == nullptr)
continue;
const ModelVolume *volume = get_model_volume(*gl_volume, objects);
if (volume == nullptr)
continue;
size_t id = volume->id().id;
if (condition.skip(id))
continue;
auto mesh = std::make_unique<sla::IndexedMesh>(caster->get_raycaster()->get_aabb_mesh());
meshes.emplace_back(std::make_pair(id, std::move(mesh)));
}*/
return meshes;
}
std::optional<RaycastManager::Hit> ray_from_camera(const RaycastManager &raycaster,
const Vec2d &mouse_pos,
const Camera &camera,
const RaycastManager::ISkip *skip)
{
Vec3d point;
Vec3d direction;
CameraUtils::ray_from_screen_pos(camera, mouse_pos, point, direction);
return raycaster.first_hit(point, direction, skip);
}
RaycastManager::AllowVolumes create_condition(const ModelVolumePtrs &volumes, const ObjectID &disallowed_volume_id) {
std::vector<size_t> allowed_volumes_id;
if (volumes.size() > 1) {
allowed_volumes_id.reserve(volumes.size() - 1);
for (const ModelVolume *v : volumes) {
// drag only above part not modifiers or negative surface
if (!v->is_model_part())
continue;
// skip actual selected object
if (v->id() == disallowed_volume_id)
continue;
allowed_volumes_id.emplace_back(v->id().id);
}
}
return RaycastManager::AllowVolumes(allowed_volumes_id);
}
} // namespace Slic3r::GUI

View File

@@ -0,0 +1,188 @@
#ifndef slic3r_RaycastManager_hpp_
#define slic3r_RaycastManager_hpp_
#include <memory> // unique_ptr
#include <optional>
#include "libslic3r/SLA/IndexedMesh.hpp" //#include "libslic3r/AABBMesh.hpp" // Structure to cast rays
#include "libslic3r/Point.hpp" // Transform3d
#include "libslic3r/ObjectID.hpp"
#include "libslic3r/Model.hpp" // ModelObjectPtrs, ModelObject, ModelInstance, ModelVolume
namespace Slic3r::GUI{
/// <summary>
/// Cast rays from camera to scene
/// Used for find hit point on model volume under mouse cursor
/// </summary>
class RaycastManager
{
// Public structures used by RaycastManager
public:
// ModelVolume.id
using Mesh = std::pair<size_t, std::unique_ptr<sla::IndexedMesh> >;//AABBMesh
using Meshes = std::vector<Mesh>;
// Key for transformation consist of unique volume and instance id ... ObjectId()
// ModelInstance, ModelVolume
using TrKey = std::pair<size_t, size_t>;
using TrItem = std::pair<TrKey, Transform3d>;
using TrItems = std::vector<TrItem>;
/// <summary>
/// Interface for identify allowed volumes to cast rays.
/// </summary>
class ISkip{
public:
virtual ~ISkip() = default;
/// <summary>
/// Condition to not process model volume
/// </summary>
/// <param name="model_volume_id">ObjectID of model volume to not process</param>
/// <returns>True on skip otherwise false</returns>
virtual bool skip(const size_t &model_volume_id) const { return false; }
};
// TODO: it is more general object move outside of this class
template<typename T>
struct SurfacePoint {
using Vec3 = Eigen::Matrix<T, 3, 1, Eigen::DontAlign>;
Vec3 position = Vec3::Zero();
Vec3 normal = Vec3::UnitZ();
};
struct Hit : public SurfacePoint<double>
{
TrKey tr_key;
double squared_distance;
};
struct ClosePoint
{
TrKey tr_key;
Vec3d point;
double squared_distance;
};
const Meshes& get_meshes() { return m_meshes; }
// Members
private:
// Keep structure to fast cast rays
// meshes are sorted by volume_id for faster search
Meshes m_meshes;
// Keep transformation of meshes
TrItems m_transformations;
// Note: one mesh could have more transformations ... instances
public:
/// <summary>
/// Actualize raycasters + transformation
/// Detection of removed object
/// Detection of removed instance
/// Detection of removed volume
/// </summary>
/// <param name="object">Model representation</param>
/// <param name="skip">Condifiton for skip actualization</param>
/// <param name="meshes">Speed up for already created AABBtrees</param>
void actualize(const ModelObject &object, const ISkip *skip = nullptr, Meshes *meshes = nullptr);
void actualize(const ModelInstance &instance, const ISkip *skip = nullptr, Meshes* meshes = nullptr);
class SkipVolume: public ISkip
{
size_t volume_id;
public:
SkipVolume(size_t volume_id) : volume_id(volume_id) {}
bool skip(const size_t &model_volume_id) const override { return model_volume_id == volume_id; }
};
class AllowVolumes: public ISkip
{
std::vector<size_t> allowed_id;
public:
AllowVolumes() = default;
AllowVolumes(std::vector<size_t> allowed_id) : allowed_id(allowed_id) {}
void clear() {
allowed_id.clear();
}
bool skip(const size_t &model_volume_id) const override {
if (allowed_id.size() == 0) {
return false;
}
auto it = std::find(allowed_id.begin(), allowed_id.end(), model_volume_id);
return it == allowed_id.end();
}
};
/// <summary>
/// Unproject on mesh and return closest hit to point in given direction
/// </summary>
/// <param name="point">Position in space</param>
/// <param name="direction">Casted ray direction</param>
/// <param name="skip">Define which caster will be skipped, null mean no skip</param>
/// <returns>Position on surface, normal direction in world coorinate
/// + key, to know hitted instance and volume</returns>
std::optional<Hit> first_hit(const Vec3d &point, const Vec3d &direction, const ISkip *skip = nullptr) const;
/// <summary>
/// Unproject Ray(point direction) on mesh to find closest hit of surface in given direction
/// NOTE: It inspect also oposit direction of ray !!
/// </summary>
/// <param name="point">Start point for ray</param>
/// <param name="direction">Direction of ray, orientation doesn't matter, both are used</param>
/// <param name="skip">Define which caster will be skipped, null mean no skip</param>
/// <returns>Position on surface, normal direction and transformation key, which define hitted object instance</returns>
std::optional<Hit> closest_hit(const Vec3d &point, const Vec3d &direction, const ISkip *skip = nullptr) const;
/// <summary>
/// Search of closest point
/// </summary>
/// <param name="point">Point</param>
/// <param name="skip">Define which caster will be skipped, null mean no skip</param>
/// <returns></returns>
std::optional<ClosePoint> closest(const Vec3d &point, const ISkip *skip = nullptr) const;
/// <summary>
/// Getter on transformation from hitted volume to world
/// </summary>
/// <param name="tr_key">Define transformation</param>
/// <returns>Transformation for key</returns>
Transform3d get_transformation(const TrKey &tr_key) const;
void clear();
};
class GLCanvas3D;
/// <summary>
/// Use scene Raycasters and prepare data for actualize RaycasterManager
/// </summary>
/// <param name="canvas">contain Scene raycasters</param>
/// <param name="condition">Limit for scene casters</param>
/// <returns>Meshes</returns>
RaycastManager::Meshes create_meshes(GLCanvas3D &canvas, const RaycastManager::AllowVolumes &condition);
struct Camera;
/// <summary>
/// Unproject on mesh by Mesh raycasters
/// </summary>
/// <param name="mouse_pos">Position of mouse on screen</param>
/// <param name="camera">Projection params</param>
/// <param name="skip">Define which caster will be skipped, null mean no skip</param>
/// <returns>Position on surface, normal direction in world coorinate
/// + key, to know hitted instance and volume</returns>
std::optional<RaycastManager::Hit> ray_from_camera(const RaycastManager &raycaster,
const Vec2d &mouse_pos,
const Camera &camera,
const RaycastManager::ISkip *skip);
/// <summary>
/// Create condition to allowe only parts from volumes without one given
/// </summary>
/// <param name="volumes">List of allowed volumes included one which is dissalowed and non parts</param>
/// <param name="disallowed_volume_id">Disallowed volume</param>
/// <returns>Condition</returns>
RaycastManager::AllowVolumes create_condition(const ModelVolumePtrs &volumes, const ObjectID &disallowed_volume_id);
} // namespace Slic3r::GUI
#endif // slic3r_RaycastManager_hpp_

View File

@@ -95,7 +95,7 @@ namespace QDT {
#define QIDI_NETWORK_LIBRARY "qidi_networking"
#define QIDI_NETWORK_AGENT_NAME "qidi_network_agent"
#define QIDI_NETWORK_AGENT_VERSION "01.09.02.05"
#define QIDI_NETWORK_AGENT_VERSION "01.10.01.01"
//iot preset type strings
#define IOT_PRINTER_TYPE_STRING "printer"
@@ -138,6 +138,9 @@ typedef std::function<void(int result, std::string info)> ResultFn;
typedef std::function<bool()> CancelFn;
typedef std::function<bool(std::map<std::string, std::string> info)> CheckFn;
//err callbacks
typedef std::function<void(std::string url, int status)> OnServerErrFn;
enum SendingPrintJobStage {
PrintingStageCreate = 0,
PrintingStageUpload = 1,
@@ -172,6 +175,17 @@ enum ConnectStatus {
ConnectStatusLost = 2,
};
struct detectResult {
std::string result_msg;
std::string command;
std::string dev_id;
std::string model_id;
std::string dev_name;
std::string version;
std::string bind_state;
std::string connect_type;
};
/* print job*/
struct PrintParams {
/* basic info */