mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-29 13:52:07 +00:00
Compare commits
1 Commits
feature/in
...
fix/ota-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
013a9452af |
@@ -233,9 +233,6 @@ void AppConfig::set_defaults()
|
||||
if (get("reverse_mouse_wheel_zoom").empty())
|
||||
set_bool("reverse_mouse_wheel_zoom", false);
|
||||
|
||||
if (get("infinite_camera_drag").empty())
|
||||
set_bool("infinite_camera_drag", false);
|
||||
|
||||
if (get("enable_append_color_by_sync_ams").empty())
|
||||
set_bool("enable_append_color_by_sync_ams", true);
|
||||
if (get("enable_merge_color_by_sync_ams").empty())
|
||||
|
||||
@@ -32,13 +32,15 @@ static void append_and_translate(ExPolygons &dst, const ExPolygons &src, const P
|
||||
for (; dst_idx < dst.size(); ++dst_idx)
|
||||
dst[dst_idx].translate(instance_shift);
|
||||
}
|
||||
// Orca: Translate the brim area into print coordinates and store it per instance.
|
||||
static void append_and_translate(const ExPolygons& src, const PrintInstance& instance,
|
||||
size_t instance_idx, std::map<ObjectInstanceID, ExPolygons>& brimAreaMap) {
|
||||
// BBS: generate brim area by objs
|
||||
static void append_and_translate(ExPolygons& dst, const ExPolygons& src,
|
||||
const PrintInstance& instance, size_t instance_idx, std::map<ObjectInstanceID, ExPolygons>& brimAreaMap) {
|
||||
ExPolygons srcShifted = src;
|
||||
Point instance_shift = instance.shift_without_plate_offset();
|
||||
for (ExPolygon& expoly : srcShifted)
|
||||
expoly.translate(instance_shift);
|
||||
for (size_t src_idx = 0; src_idx < srcShifted.size(); ++src_idx)
|
||||
srcShifted[src_idx].translate(instance_shift);
|
||||
srcShifted = diff_ex(srcShifted, dst);
|
||||
//expolygons_append(dst, temp2);
|
||||
expolygons_append(brimAreaMap[{ instance.print_object->id(), instance_idx }], std::move(srcShifted));
|
||||
}
|
||||
|
||||
@@ -570,7 +572,7 @@ static ExPolygons outer_inner_brim_area(const Print& print,
|
||||
for (size_t instance_idx = 0; instance_idx < object->instances().size(); ++instance_idx) {
|
||||
const PrintInstance& instance = object->instances()[instance_idx];
|
||||
if (!brim_area_object.empty())
|
||||
append_and_translate(brim_area_object, instance, instance_idx, brimAreaMap);
|
||||
append_and_translate(brim_area, brim_area_object, instance, instance_idx, brimAreaMap);
|
||||
append_and_translate(no_brim_area, no_brim_area_object, instance);
|
||||
append_and_translate(holes, holes_object, instance);
|
||||
append_and_translate(objectIslands, objectIsland, instance);
|
||||
@@ -873,14 +875,6 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_
|
||||
ExPolygons islands_area_ex = outer_inner_brim_area(print,
|
||||
float(flow.scaled_spacing()), brimAreaMap, objPrintVec, printExtruders);
|
||||
|
||||
if (!print.config().combine_brims) {
|
||||
ExPolygons claimed_area;
|
||||
for (auto& [_, areas] : brimAreaMap) {
|
||||
areas = diff_ex(areas, claimed_area);
|
||||
expolygons_append(claimed_area, areas);
|
||||
}
|
||||
}
|
||||
|
||||
// BBS: Find boundingbox of the first layer
|
||||
for (const ObjectID printObjID : print.print_object_ids()) {
|
||||
BoundingBox bbx;
|
||||
|
||||
@@ -4535,16 +4535,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
else if (evt.Dragging() || is_camera_rotate(evt, button_mappings) || is_camera_pan(evt, button_mappings)) {
|
||||
m_mouse.dragging = true;
|
||||
|
||||
// Orca: this event reports the position the pointer was teleported to by the infinite
|
||||
// camera drag. Restart the drag from there, so the jump is not turned into a camera
|
||||
// movement. Dropping the origin also keeps the drag consistent on platforms which
|
||||
// silently ignore the warp request (Wayland), where the pointer never actually moved.
|
||||
if (m_mouse.drag.pointer_wrapped) {
|
||||
m_mouse.drag.pointer_wrapped = false;
|
||||
m_mouse.set_start_position_2D_as_invalid();
|
||||
m_mouse.set_start_position_3D_as_invalid();
|
||||
}
|
||||
|
||||
if (m_layers_editing.state != LayersEditing::Unknown && layer_editing_object_idx != -1) {
|
||||
if (m_layers_editing.state == LayersEditing::Editing) {
|
||||
_perform_layer_editing_action(&evt);
|
||||
@@ -4626,7 +4616,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
camera.auto_type(Camera::EType::Perspective);
|
||||
m_dirty = true;
|
||||
m_mouse.ignore_right_up = true; // will be reset on button up event even if not right button is pressed
|
||||
_wrap_mouse_pointer_on_canvas_border(pos);
|
||||
}
|
||||
|
||||
m_camera_movement = true;
|
||||
@@ -4653,7 +4642,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
camera.set_target(camera.get_target() + orig - cur_pos);
|
||||
m_dirty = true;
|
||||
m_mouse.ignore_right_up = true; // will be reset on button up event even if not right button is pressed
|
||||
_wrap_mouse_pointer_on_canvas_border(pos);
|
||||
}
|
||||
|
||||
m_camera_movement = true;
|
||||
@@ -5541,7 +5529,6 @@ void GLCanvas3D::mouse_up_cleanup()
|
||||
m_moving = false;
|
||||
m_camera_movement = false;
|
||||
m_mouse.drag.move_volume_idx = -1;
|
||||
m_mouse.drag.pointer_wrapped = false;
|
||||
m_mouse.set_start_position_3D_as_invalid();
|
||||
m_mouse.set_start_position_2D_as_invalid();
|
||||
m_mouse.dragging = false;
|
||||
@@ -10239,47 +10226,6 @@ Vec3d GLCanvas3D::_mouse_to_bed_3d(const Point& mouse_pos)
|
||||
return mouse_ray(mouse_pos).intersect_plane(0.0);
|
||||
}
|
||||
|
||||
// Orca: Blender-like infinite camera drag. Once a pan/orbit drag reaches a canvas border the
|
||||
// pointer is teleported to the opposite one, so that the movement is only limited by how long
|
||||
// the user keeps dragging and not by the window (or screen) bounds.
|
||||
// The drag is flagged instead of being offset by the jump, because the warp request is not
|
||||
// honoured everywhere - Wayland compositors ignore it, in which case the pointer stays at the
|
||||
// border and the drag simply stops there, exactly as it does with this feature disabled.
|
||||
void GLCanvas3D::_wrap_mouse_pointer_on_canvas_border(const Point& mouse_pos)
|
||||
{
|
||||
if (m_canvas == nullptr || !wxGetApp().app_config->get_bool("infinite_camera_drag"))
|
||||
return;
|
||||
|
||||
const Size cnv_size = get_canvas_size();
|
||||
|
||||
auto wrapped_coord = [](int coord, int size) {
|
||||
// The pointer is teleported once it comes this close to a border and lands the same
|
||||
// distance away from the opposite one, so that it never wraps back on the next event.
|
||||
// The margin is proportional to the canvas because the pointer can travel a lot between
|
||||
// two motion events of a fast drag, and the border would be missed if it were too thin.
|
||||
const int border = std::clamp(size / 32, 12, 48);
|
||||
const int span = size - 2 * border;
|
||||
// Nothing to wrap into if the canvas is smaller than the two margins.
|
||||
if (span <= 0 || (coord >= border && coord <= size - border))
|
||||
return coord;
|
||||
// Clamping matters when the pointer is reported far outside of the canvas.
|
||||
return std::clamp(coord + (coord < border ? span : -span), border, size - border);
|
||||
};
|
||||
|
||||
const Point wrapped(wrapped_coord(static_cast<int>(mouse_pos.x()), cnv_size.get_width()),
|
||||
wrapped_coord(static_cast<int>(mouse_pos.y()), cnv_size.get_height()));
|
||||
if (wrapped == mouse_pos)
|
||||
return;
|
||||
|
||||
Vec2d logical_pos = wrapped.cast<double>();
|
||||
#if ENABLE_RETINA_GL
|
||||
const double factor = m_retina_helper->get_scale_factor();
|
||||
logical_pos /= factor;
|
||||
#endif // ENABLE_RETINA_GL
|
||||
m_canvas->WarpPointer(static_cast<int>(std::lround(logical_pos.x())), static_cast<int>(std::lround(logical_pos.y())));
|
||||
m_mouse.drag.pointer_wrapped = true;
|
||||
}
|
||||
|
||||
// While it looks like we can call
|
||||
// this->reload_scene(true, true)
|
||||
// the two functions are quite different:
|
||||
|
||||
@@ -333,9 +333,6 @@ class GLCanvas3D
|
||||
int move_volume_idx{ -1 };
|
||||
bool move_requires_threshold{ false };
|
||||
Point move_start_threshold_position_2D{ Invalid_2D_Point };
|
||||
// Orca: set when the pointer has been teleported to the opposite canvas border
|
||||
// by the infinite camera drag, see GLCanvas3D::_wrap_mouse_pointer_on_canvas_border()
|
||||
bool pointer_wrapped{ false };
|
||||
};
|
||||
|
||||
bool dragging{ false };
|
||||
@@ -1224,10 +1221,6 @@ public:
|
||||
private:
|
||||
bool _is_shown_on_screen() const;
|
||||
|
||||
// Orca: teleports the pointer to the opposite canvas border when a camera drag reaches
|
||||
// one, so that panning/orbiting is not limited by the window bounds.
|
||||
void _wrap_mouse_pointer_on_canvas_border(const Point& mouse_pos);
|
||||
|
||||
void _update_slice_error_status();
|
||||
|
||||
void _switch_toolbars_icon_filename();
|
||||
|
||||
@@ -1785,9 +1785,6 @@ void PreferencesDialog::create_items()
|
||||
auto reverse_mouse_zoom = create_item_checkbox(_L("Reverse mouse zoom"), _L("If enabled, reverses the direction of zoom with mouse wheel."), "reverse_mouse_wheel_zoom");
|
||||
g_sizer->Add(reverse_mouse_zoom);
|
||||
|
||||
auto item_infinite_camera_drag = create_item_checkbox(_L("Infinite camera drag"), _L("If enabled, the mouse pointer is teleported to the opposite side of the 3D view when it reaches a border while panning or orbiting, so camera movement is not limited by the window bounds."), "infinite_camera_drag");
|
||||
g_sizer->Add(item_infinite_camera_drag);
|
||||
|
||||
std::vector<wxString> ButtonDragActions = {_L("None"), _L("Pan"), _L("Rotate")};
|
||||
auto item_left_mouse_drag = create_item_combobox(_L("Left Mouse Drag"), _L("Set the action that dragging the left mouse button should perform."), "left_mouse_drag_action", ButtonDragActions);
|
||||
g_sizer->Add(item_left_mouse_drag);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#include "PresetUpdater.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/filesystem/directory.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <functional>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <ostream>
|
||||
@@ -19,6 +21,7 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <wx/app.h>
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
@@ -204,7 +207,6 @@ struct PresetUpdater::priv
|
||||
|
||||
// Per-vendor update checking
|
||||
std::set<std::string> checked_vendors;
|
||||
std::mutex vendor_check_mutex;
|
||||
std::vector<std::thread> vendor_check_threads;
|
||||
std::atomic<bool> vendor_check_cancel{false};
|
||||
|
||||
@@ -221,10 +223,10 @@ struct PresetUpdater::priv
|
||||
priv();
|
||||
|
||||
void set_download_prefs(AppConfig *app_config);
|
||||
bool get_file(const std::string &url, const fs::path &target_path) const;
|
||||
//BBS: refine preset update logic
|
||||
bool get_file(const std::string &url, const fs::path &target_path) const;
|
||||
//BBS: refine preset update logic
|
||||
bool extract_file(const fs::path &source_path, const fs::path &dest_path = {});
|
||||
void prune_tmps() const;
|
||||
void prune_tmp(const std::string& vendor_id) 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="");
|
||||
@@ -371,14 +373,14 @@ bool PresetUpdater::priv::extract_file(const fs::path &source_path, const fs::pa
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove leftover paritally downloaded files, if any.
|
||||
void PresetUpdater::priv::prune_tmps() const
|
||||
// Remove a leftover partial archive for the vendor about to be synchronized.
|
||||
void PresetUpdater::priv::prune_tmp(const std::string& vendor_id) const
|
||||
{
|
||||
for (auto &dir_entry : boost::filesystem::directory_iterator(cache_path))
|
||||
if (is_plain_file(dir_entry) && dir_entry.path().extension() == TMP_EXTENSION) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "[Orca Updater]remove old cached files: " << dir_entry.path().string();
|
||||
fs::remove(dir_entry.path());
|
||||
}
|
||||
boost::system::error_code ec;
|
||||
const fs::path tmp_path = cache_path / (vendor_id + TMP_EXTENSION);
|
||||
fs::remove(tmp_path, ec);
|
||||
if (ec)
|
||||
BOOST_LOG_TRIVIAL(warning) << "[Orca Updater]failed to remove " << tmp_path.string() << ": " << ec.message();
|
||||
}
|
||||
|
||||
//BBS: refine the Preset Updater logic
|
||||
@@ -1060,10 +1062,9 @@ void PresetUpdater::priv::check_installed_vendor_profiles() const
|
||||
Semver resource_ver = get_version_from_json(file_path);
|
||||
Semver vendor_ver = get_version_from_json(path_in_vendor.string());
|
||||
|
||||
bool version_match = ((resource_ver.maj() == vendor_ver.maj()) && (resource_ver.min() == vendor_ver.min()));
|
||||
|
||||
if (!version_match || (vendor_ver < resource_ver)) {
|
||||
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:found vendor "<<vendor_name<<" newer version "<<resource_ver.to_string() <<" from resource, old version "<<vendor_ver.to_string();
|
||||
if (vendor_ver < resource_ver) {
|
||||
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:found vendor " << vendor_name << " newer version "
|
||||
<< resource_ver.to_string() << " from resource, old version " << vendor_ver.to_string();
|
||||
bundles.insert(vendor_name);
|
||||
}
|
||||
}
|
||||
@@ -1305,49 +1306,29 @@ PresetUpdater::~PresetUpdater()
|
||||
|
||||
//BBS: change directories by design
|
||||
//BBS: refine the preset updater logic
|
||||
void PresetUpdater::sync(std::string http_url, std::string language, std::string plugin_version, PresetBundle *preset_bundle)
|
||||
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; }
|
||||
|
||||
// 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{};
|
||||
|
||||
// Determine active vendor before entering the thread
|
||||
std::string active_vendor;
|
||||
if (preset_bundle) {
|
||||
const Preset& printer = preset_bundle->printers.get_edited_preset();
|
||||
if (printer.vendor)
|
||||
active_vendor = printer.vendor->id;
|
||||
}
|
||||
|
||||
p->thread = std::thread([this, vendors, active_vendor, http_url, language, plugin_version]() {
|
||||
this->p->prune_tmps();
|
||||
if (p->cancel)
|
||||
return;
|
||||
this->p->sync_version();
|
||||
if (p->cancel)
|
||||
return;
|
||||
// Per-vendor config check for the active vendor at startup
|
||||
if (!active_vendor.empty() && !vendors.empty()) {
|
||||
this->p->sync_vendor_config(active_vendor);
|
||||
if (p->cancel)
|
||||
return;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(this->p->vendor_check_mutex);
|
||||
this->p->checked_vendors.insert(active_vendor);
|
||||
}
|
||||
}
|
||||
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);
|
||||
p->thread = std::thread([this, http_url, language, plugin_version]() {
|
||||
try {
|
||||
this->p->sync_version();
|
||||
if (p->cancel)
|
||||
return;
|
||||
// Vendor profile updates are triggered by check_vendor_update()
|
||||
// after the startup printer preset has been restored.
|
||||
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);
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "[Orca Updater] background sync failed: " << e.what();
|
||||
} catch (...) {
|
||||
BOOST_LOG_TRIVIAL(error) << "[Orca Updater] background sync failed with an unknown exception";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1356,16 +1337,17 @@ void PresetUpdater::check_vendor_update(const std::string& vendor_id)
|
||||
if (!p->enabled_config_update) return;
|
||||
if (vendor_id.empty()) return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(p->vendor_check_mutex);
|
||||
|
||||
if (!p->checked_vendors.insert(vendor_id).second)
|
||||
return;
|
||||
|
||||
p->vendor_check_threads.emplace_back([this, vendor_id]() {
|
||||
try {
|
||||
this->p->prune_tmp(vendor_id);
|
||||
this->p->sync_vendor_config(vendor_id);
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "[Orca Updater] vendor update failed for " << vendor_id << ": " << e.what();
|
||||
} catch (...) {
|
||||
BOOST_LOG_TRIVIAL(error) << "[Orca Updater] vendor update failed for " << vendor_id << " with an unknown exception";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -153,24 +153,6 @@ TEST_CASE("Object brims are generated per instance", "[SkirtBrim]")
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Uncombined neighboring brims precede their respective objects", "[SkirtBrim]")
|
||||
{
|
||||
Print print;
|
||||
Model model;
|
||||
place_two_cubes_apart(0, {
|
||||
{ "skirt_loops", 0 },
|
||||
{ "brim_type", "outer_only" },
|
||||
{ "brim_width", 5 },
|
||||
{ "combine_brims", 0 },
|
||||
}, print, model);
|
||||
print.process();
|
||||
|
||||
REQUIRE(print.skirt_brim_groups().size() == 1);
|
||||
REQUIRE(print.skirt_brim_groups().front().brims.size() == 2);
|
||||
CHECK(role_sequence(gcode(print), { "brim", "perimeter" }) ==
|
||||
std::vector<std::string>{ "brim", "perimeter", "brim", "perimeter" });
|
||||
}
|
||||
|
||||
TEST_CASE("Combine brims merges neighboring object instances", "[SkirtBrim]")
|
||||
{
|
||||
Print print;
|
||||
|
||||
Reference in New Issue
Block a user