Merge branch 'main' into bugfox/infill-pattern-options

This commit is contained in:
SoftFever 2025-02-19 19:39:06 +08:00 committed by GitHub
commit 0ec13678e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
263 changed files with 29244 additions and 13120 deletions

View file

@ -258,7 +258,7 @@ void AMSMaterialsSetting::create_panel_normal(wxWindow* parent)
m_panel_SN->Fit();
wxBoxSizer* m_tip_sizer = new wxBoxSizer(wxHORIZONTAL);
m_tip_readonly = new Label(parent, _L(""));
m_tip_readonly = new Label(parent, L"");
m_tip_readonly->SetForegroundColour(*wxBLACK);
m_tip_readonly->SetBackgroundColour(*wxWHITE);
m_tip_readonly->SetMinSize(wxSize(FromDIP(380), -1));

View file

@ -527,6 +527,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
bool has_spiral_vase = config->opt_bool("spiral_mode");
toggle_line("spiral_mode_smooth", has_spiral_vase);
toggle_line("spiral_mode_max_xy_smoothing", has_spiral_vase && config->opt_bool("spiral_mode_smooth"));
toggle_line("spiral_starting_flow_ratio", has_spiral_vase);
toggle_line("spiral_finishing_flow_ratio", has_spiral_vase);
bool has_top_shell = config->opt_int("top_shell_layers") > 0;
bool has_bottom_shell = config->opt_int("bottom_shell_layers") > 0;
bool has_solid_infill = has_top_shell || has_bottom_shell;
@ -568,7 +570,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
bool have_brim = (config->opt_enum<BrimType>("brim_type") != btNoBrim);
toggle_field("brim_object_gap", have_brim);
bool have_brim_width = (config->opt_enum<BrimType>("brim_type") != btNoBrim) && config->opt_enum<BrimType>("brim_type") != btAutoBrim;
bool have_brim_width = (config->opt_enum<BrimType>("brim_type") != btNoBrim) && config->opt_enum<BrimType>("brim_type") != btAutoBrim &&
config->opt_enum<BrimType>("brim_type") != btPainted;
toggle_field("brim_width", have_brim_width);
// wall_filament uses the same logic as in Print::extruders()
toggle_field("wall_filament", have_perimeters || have_brim);
@ -783,6 +786,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_line("interlocking_beam_layer_count", use_beam_interlocking);
toggle_line("interlocking_depth", use_beam_interlocking);
toggle_line("interlocking_boundary_avoidance", use_beam_interlocking);
bool lattice_options = config->opt_enum<InfillPattern>("sparse_infill_pattern") == InfillPattern::ip2DLattice;
for (auto el : { "lattice_angle_1", "lattice_angle_2"})
toggle_line(el, lattice_options);
}
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)

View file

@ -1441,6 +1441,8 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject
&& !vol->is_modifier) {
vol->force_neutral_color = true;
}
else if (gizmo_type == GLGizmosManager::BrimEars)
vol->force_neutral_color = false;
else if (gizmo_type == GLGizmosManager::MmuSegmentation)
vol->is_active = false;
else
@ -1539,15 +1541,22 @@ void GLCanvas3D::refresh_camera_scene_box()
BoundingBoxf3 GLCanvas3D::volumes_bounding_box(bool current_plate_only) const
{
BoundingBoxf3 bb;
PartPlate *plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
BoundingBoxf3 expand_part_plate_list_box;
bool is_limit = m_canvas_type != ECanvasType::CanvasAssembleView;
if (is_limit) {
auto plate_list_box = current_plate_only ? wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_bounding_box() :
wxGetApp().plater()->get_partplate_list().get_bounding_box();
auto horizontal_radius = 0.5 * sqrt(std::pow(plate_list_box.min[0] - plate_list_box.max[0], 2) + std::pow(plate_list_box.min[1] - plate_list_box.max[1], 2));
const float scale = 2;
expand_part_plate_list_box.merge(plate_list_box.min - scale * Vec3d(horizontal_radius, horizontal_radius, 0));
expand_part_plate_list_box.merge(plate_list_box.max + scale * Vec3d(horizontal_radius, horizontal_radius, 0));
}
for (const GLVolume *volume : m_volumes.volumes) {
if (!m_apply_zoom_to_volumes_filter || ((volume != nullptr) && volume->zoom_to_volumes)) {
const auto plate_bb = plate->get_bounding_box();
const auto v_bb = volume->transformed_bounding_box();
if (!plate_bb.overlap(v_bb))
continue;
bb.merge(v_bb);
const auto v_bb = volume->transformed_bounding_box();
if (is_limit && !expand_part_plate_list_box.overlap(v_bb))
continue;
bb.merge(v_bb);
}
}
return bb;
@ -1893,6 +1902,7 @@ void GLCanvas3D::render(bool only_init)
//BBS add partplater rendering logic
bool only_current = false, only_body = false, show_axes = true, no_partplate = false;
bool show_grid = true;
GLGizmosManager::EType gizmo_type = m_gizmos.get_current_type();
if (!m_main_toolbar.is_enabled()) {
//only_body = true;
@ -1900,6 +1910,8 @@ void GLCanvas3D::render(bool only_init)
}
else if ((gizmo_type == GLGizmosManager::FdmSupports) || (gizmo_type == GLGizmosManager::Seam) || (gizmo_type == GLGizmosManager::MmuSegmentation))
no_partplate = true;
else if (gizmo_type == GLGizmosManager::BrimEars && !camera.is_looking_downward())
show_grid = false;
/* view3D render*/
int hover_id = (m_hover_plate_idxs.size() > 0)?m_hover_plate_idxs.front():-1;
@ -1911,7 +1923,7 @@ void GLCanvas3D::render(bool only_init)
if (!no_partplate)
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
if (!no_partplate) //BBS: add outline logic
_render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true);
_render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true, show_grid);
_render_objects(GLVolumeCollection::ERenderType::Transparent, !m_gizmos.is_running());
}
/* preview render */
@ -7162,9 +7174,9 @@ void GLCanvas3D::_render_bed(const Transform3d& view_matrix, const Transform3d&
m_bed.render(*this, view_matrix, projection_matrix, bottom, scale_factor, show_axes);
}
void GLCanvas3D::_render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali)
void GLCanvas3D::_render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali, bool show_grid)
{
wxGetApp().plater()->get_partplate_list().render(view_matrix, projection_matrix, bottom, only_current, only_body, hover_id, render_cali);
wxGetApp().plater()->get_partplate_list().render(view_matrix, projection_matrix, bottom, only_current, only_body, hover_id, render_cali, show_grid);
}
void GLCanvas3D::_render_plane() const

View file

@ -1161,7 +1161,7 @@ private:
void _render_background();
void _render_bed(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_axes);
//BBS: add part plate related logic
void _render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body = false, int hover_id = -1, bool render_cali = false);
void _render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body = false, int hover_id = -1, bool render_cali = false, bool show_grid = true);
//BBS: add outline drawing logic
void _render_objects(GLVolumeCollection::ERenderType type, bool with_outline = true);
//BBS: GUI refactor: add canvas size as parameters

View file

@ -105,7 +105,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CAT
}},
{ L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", L("Top Solid Layers"),1},{"top_shell_thickness", L("Top Minimum Shell Thickness"),1},
{"bottom_shell_layers", L("Bottom Solid Layers"),1}, {"bottom_shell_thickness", L("Bottom Minimum Shell Thickness"),1},
{"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"infill_anchor", "",1},{"infill_anchor_max", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1},
{"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"lattice_angle_1", "",1},{"lattice_angle_2", "",1},{"infill_anchor", "",1},{"infill_anchor_max", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1},
{"infill_combination", "",1}, {"infill_combination_max_layer_height", "",1}, {"infill_wall_overlap", "",1},{"top_bottom_infill_wall_overlap", "",1}, {"solid_infill_direction", "",1}, {"rotate_solid_infill_direction", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"internal_bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1}
}},
{ L("Speed"), {{"outer_wall_speed", "",1},{"inner_wall_speed", "",2},{"sparse_infill_speed", "",3},{"top_surface_speed", "",4}, {"internal_solid_infill_speed", "",5},

View file

@ -74,11 +74,11 @@ PickingModel GLGizmoBase::Grabber::s_cone;
GLGizmoBase::Grabber::~Grabber()
{
if (s_cube.model.is_initialized())
s_cube.model.reset();
//if (s_cube.model.is_initialized())
// s_cube.model.reset();
if (s_cone.model.is_initialized())
s_cone.model.reset();
//if (s_cone.model.is_initialized())
// s_cone.model.reset();
}
float GLGizmoBase::Grabber::get_half_size(float size) const

View file

@ -32,6 +32,7 @@ class ImGuiWrapper;
class GLCanvas3D;
enum class CommonGizmosDataID;
class CommonGizmosDataPool;
class Selection;
class GLGizmoBase
{

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,180 @@
#ifndef slic3r_GLGizmoBrimEars_hpp_
#define slic3r_GLGizmoBrimEars_hpp_
#include "GLGizmoBase.hpp"
#include "slic3r/GUI/GLSelectionRectangle.hpp"
#include "libslic3r/BrimEarsPoint.hpp"
#include "libslic3r/ObjectID.hpp"
namespace Slic3r {
class ConfigOption;
namespace GUI {
enum class SLAGizmoEventType : unsigned char;
class GLGizmoBrimEars : public GLGizmoBase
{
private:
using PickRaycaster = SceneRaycasterItem;
bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
bool unproject_on_mesh2(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
const float RenderPointScale = 1.f;
class CacheEntry {
public:
CacheEntry() :
brim_point(BrimPoint()),
selected(false),
normal(Vec3f(0, 0, 1)),
is_hover(false),
is_error(false)
{}
CacheEntry(const BrimPoint &point, bool sel = false, const Vec3f &norm = Vec3f(0, 0, 1), bool hover = false, bool error = false)
: brim_point(point), selected(sel), normal(norm), is_hover(hover), is_error(error)
{}
bool operator==(const CacheEntry& rhs) const {
return (brim_point == rhs.brim_point);
}
bool operator!=(const CacheEntry& rhs) const {
return ! ((*this) == rhs);
}
inline bool pos_is_zero() {
return brim_point.pos.isZero();
}
void set_empty() {
brim_point = BrimPoint();
selected = false;
normal.setZero();
is_hover = false;
is_error = false;
}
BrimPoint brim_point;
bool selected; // whether the point is selected
bool is_hover; // show mouse hover cylinder
bool is_error;
Vec3f normal;
template<class Archive>
void serialize(Archive & ar)
{
ar(brim_point, selected, normal);
}
};
public:
GLGizmoBrimEars(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
virtual ~GLGizmoBrimEars() = default;
void data_changed(bool is_serializing) override;
void set_brim_data();
bool on_mouse(const wxMouseEvent& mouse_event) override;
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
void delete_selected_points();
void save_model();
//ClippingPlane get_sla_clipping_plane() const;
bool is_selection_rectangle_dragging() const { return m_selection_rectangle.is_dragging(); }
bool wants_enter_leave_snapshots() const override { return true; }
std::string get_gizmo_entering_text() const override { return "Entering Brim Ears"; }
std::string get_gizmo_leaving_text() const override { return "Leaving Brim Ears"; }
private:
bool on_init() override;
void on_dragging(const UpdateData& data) override;
void on_render() override;
void render_points(const Selection& selection);
float m_new_point_head_diameter; // Size of a new point.
float m_max_angle = 125.f;
float m_detection_radius = 1.f;
double m_detection_radius_max = .0f;
CacheEntry m_point_before_drag; // undo/redo - so we know what state was edited
float m_old_point_head_diameter = 0.; // the same
mutable std::vector<CacheEntry> m_editing_cache; // a support point and whether it is currently selectedchanges or undo/redo
std::map<int, CacheEntry> m_single_brim;
ObjectID m_old_mo_id;
const Vec3d m_world_normal = {0, 0, 1};
std::map<GLVolume*, std::shared_ptr<PickRaycaster>> m_mesh_raycaster_map;
GLVolume* m_last_hit_volume;
CacheEntry* render_hover_point = nullptr;
bool m_link_text_hover = false;
PickingModel m_cylinder;
// This map holds all translated description texts, so they can be easily referenced during layout calculations
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
std::map<std::string, wxString> m_desc;
GLSelectionRectangle m_selection_rectangle;
ExPolygons m_first_layer;
bool m_wait_for_up_event = false;
bool m_selection_empty = true;
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)
std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
bool is_mesh_point_clipped(const Vec3d& point) const;
// Methods that do the model_object and editing cache synchronization,
// editing mode selection, etc:
enum {
AllPoints = -2,
NoPoints,
};
void select_point(int i);
void unselect_point(int i);
void reload_cache();
Points generate_points(Polygon &obj_polygon, float ear_detection_length, float brim_ears_max_angle, bool is_outer);
void auto_generate();
void first_layer_slicer();
void get_detection_radius_max();
void update_raycasters();
protected:
void on_set_state() override;
void on_set_hover_id() override
{
if ((int)m_editing_cache.size() <= m_hover_id)
m_hover_id = -1;
}
void on_start_dragging() override;
void on_stop_dragging() override;
void on_render_input_window(float x, float y, float bottom_limit) override;
void show_tooltip_information(float x, float y);
std::string on_get_name() const override;
bool on_is_activable() const override;
//bool on_is_selectable() const override;
virtual CommonGizmosDataID on_get_requirements() const override;
void on_load(cereal::BinaryInputArchive& ar) override;
void on_save(cereal::BinaryOutputArchive& ar) const override;
virtual void on_register_raycasters_for_picking() override;
virtual void on_unregister_raycasters_for_picking() override;
void register_single_mesh_pick();
//void update_single_mesh_pick(GLVolume* v);
void reset_all_pick();
bool add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal);
float get_brim_default_radius() const;
ExPolygon make_polygon(BrimPoint point, const Geometry::Transformation &trsf);
void find_single();
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoBrimEars_hpp_

View file

@ -312,6 +312,11 @@ void ObjectClipper::render_cut(const std::vector<size_t>* ignore_idxs) const
}
}
void ObjectClipper::set_position_to_init_layer()
{
m_clp.reset(new ClippingPlane({0, 0, 1}, 0.1));
get_pool()->get_canvas()->set_as_dirty();
}
int ObjectClipper::get_number_of_contours() const
{
@ -351,17 +356,22 @@ std::vector<Vec3d> ObjectClipper::point_per_contour() const
}
void ObjectClipper::set_position_by_ratio(double pos, bool keep_normal)
void ObjectClipper::set_position_by_ratio(double pos, bool keep_normal, bool vertical_normal)
{
const ModelObject* mo = get_pool()->selection_info()->model_object();
int active_inst = get_pool()->selection_info()->get_active_instance();
double z_shift = get_pool()->selection_info()->get_sla_shift();
//Vec3d camera_dir = wxGetApp().plater()->get_camera().get_dir_forward();
//if (abs(camera_dir(0)) > EPSILON || abs(camera_dir(1)) > EPSILON)
// camera_dir(2) = 0;
Vec3d normal;
if(vertical_normal) {
normal = {0, 0, 1};
}else {
//Vec3d camera_dir = wxGetApp().plater()->get_camera().get_dir_forward();
//if (abs(camera_dir(0)) > EPSILON || abs(camera_dir(1)) > EPSILON)
// camera_dir(2) = 0;
Vec3d normal = (keep_normal && m_clp) ? m_clp->get_normal() : /*-camera_dir;*/ -wxGetApp().plater()->get_camera().get_dir_forward();
normal = (keep_normal && m_clp) ? m_clp->get_normal() : /*-camera_dir;*/ -wxGetApp().plater()->get_camera().get_dir_forward();
}
Vec3d center;
if (get_pool()->get_canvas()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) {

View file

@ -232,9 +232,10 @@ public:
CommonGizmosDataID get_dependencies() const override { return CommonGizmosDataID::SelectionInfo; }
#endif // NDEBUG
double get_position() const { return m_clp_ratio; }
void set_position_to_init_layer();
const ClippingPlane* get_clipping_plane(bool ignore_hide_clipped = false) const;
void render_cut(const std::vector<size_t>* ignore_idxs = nullptr) const;
void set_position_by_ratio(double pos, bool keep_normal);
void set_position_by_ratio(double pos, bool keep_normal, bool vertical_normal=false);
void set_range_and_pos(const Vec3d& cpl_normal, double cpl_offset, double pos);
void set_behavior(bool hide_clipped, bool fill_cut, double contour_width);

View file

@ -15,6 +15,7 @@
#include "slic3r/GUI/Gizmos/GLGizmoFlatten.hpp"
//#include "slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoCut.hpp"
//#include "slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp"
//#include "slic3r/GUI/Gizmos/GLGizmoHollow.hpp"
@ -206,6 +207,7 @@ bool GLGizmosManager::init()
m_gizmos.emplace_back(new GLGizmoMeasure(m_parent, m_is_dark ? "toolbar_measure_dark.svg" : "toolbar_measure.svg", EType::Measure));
m_gizmos.emplace_back(new GLGizmoAssembly(m_parent, m_is_dark ? "toolbar_assembly_dark.svg" : "toolbar_assembly.svg", EType::Assembly));
m_gizmos.emplace_back(new GLGizmoSimplify(m_parent, "reduce_triangles.svg", EType::Simplify));
m_gizmos.emplace_back(new GLGizmoBrimEars(m_parent, m_is_dark ? "toolbar_brimears_dark.svg" : "toolbar_brimears.svg", EType::BrimEars));
//m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", sprite_id++));
//m_gizmos.emplace_back(new GLGizmoFaceDetector(m_parent, "face recognition.svg", sprite_id++));
//m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", sprite_id++));
@ -453,6 +455,8 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
return dynamic_cast<GLGizmoCut3D*>(m_gizmos[Cut].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == MeshBoolean)
return dynamic_cast<GLGizmoMeshBoolean*>(m_gizmos[MeshBoolean].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == BrimEars)
return dynamic_cast<GLGizmoBrimEars*>(m_gizmos[BrimEars].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else
return false;
}
@ -543,7 +547,7 @@ bool GLGizmosManager::on_mouse_wheel(const wxMouseEvent &evt)
{
bool processed = false;
if (/*m_current == SlaSupports || m_current == Hollow ||*/ m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) {
if (/*m_current == SlaSupports || m_current == Hollow ||*/ m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == BrimEars) {
float rot = (float)evt.GetWheelRotation() / (float)evt.GetWheelDelta();
if (gizmo_event((rot > 0.f ? SLAGizmoEventType::MouseWheelUp : SLAGizmoEventType::MouseWheelDown), Vec2d::Zero(), evt.ShiftDown(), evt.AltDown()
// BBS
@ -813,21 +817,25 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
int keyCode = evt.GetKeyCode();
bool processed = false;
if (evt.GetEventType() == wxEVT_KEY_UP) {
/*if (m_current == SlaSupports || m_current == Hollow)
if (evt.GetEventType() == wxEVT_KEY_UP)
{
if (/*m_current == SlaSupports || m_current == Hollow ||*/ m_current == BrimEars)
{
bool is_editing = true;
bool is_rectangle_dragging = false;
if (m_current == SlaSupports) {
/*if (m_current == SlaSupports) {
GLGizmoSlaSupports* gizmo = dynamic_cast<GLGizmoSlaSupports*>(get_current());
is_editing = gizmo->is_in_editing_mode();
is_rectangle_dragging = gizmo->is_selection_rectangle_dragging();
}
else {
GLGizmoHollow* gizmo = dynamic_cast<GLGizmoHollow*>(get_current());
} else*/ if (m_current == BrimEars) {
GLGizmoBrimEars* gizmo = dynamic_cast<GLGizmoBrimEars*>(get_current());
is_rectangle_dragging = gizmo->is_selection_rectangle_dragging();
}
/*else {
GLGizmoHollow* gizmo = dynamic_cast<GLGizmoHollow*>(get_current());
is_rectangle_dragging = gizmo->is_selection_rectangle_dragging();
}*/
if (keyCode == WXK_SHIFT)
{
@ -847,7 +855,7 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
// capture number key
processed = true;
}
}*/
}
if (m_current == Measure || m_current == Assembly) {
if (keyCode == WXK_CONTROL)
gizmo_event(SLAGizmoEventType::CtrlUp, Vec2d::Zero(), evt.ShiftDown(), evt.AltDown(), evt.CmdDown());
@ -865,7 +873,12 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
// m_parent.set_cursor(GLCanvas3D::Cross);
processed = true;
}
else*/ if (m_current == Cut) {
else*/ if ((m_current == BrimEars) && ((keyCode == WXK_SHIFT) || (keyCode == WXK_ALT)))
{
processed = true;
}
else if (m_current == Cut)
{
auto do_move = [this, &processed](double delta_z) {
GLGizmoCut3D* cut = dynamic_cast<GLGizmoCut3D*>(get_current());
cut->shift_cut(delta_z);
@ -1324,11 +1337,15 @@ bool GLGizmosManager::grabber_contains_mouse() const
bool GLGizmosManager::is_in_editing_mode(bool error_notification) const
{
//if (m_current != SlaSupports || ! dynamic_cast<GLGizmoSlaSupports*>(get_current())->is_in_editing_mode())
/*if (m_current == SlaSupports && dynamic_cast<GLGizmoSlaSupports*>(get_current())->is_in_editing_mode()) {
return true;
} else*/ if (m_current == BrimEars) {
dynamic_cast<GLGizmoBrimEars*>(get_current())->save_model();
return false;
} else {
return false;
}
// BBS: remove SLA editing notification
//return true;
}

View file

@ -88,6 +88,7 @@ public:
Measure,
Assembly,
Simplify,
BrimEars,
//SlaSupports,
// BBS
//FaceRecognition,

View file

@ -416,7 +416,7 @@ void ImGuiWrapper::set_language(const std::string &language)
}
else if (lang == "en") {
ranges = ImGui::GetIO().Fonts->GetGlyphRangesEnglish(); // Basic Latin
}
}
else{
ranges = ImGui::GetIO().Fonts->GetGlyphRangesOthers();
}
@ -560,6 +560,15 @@ ImVec2 ImGuiWrapper::calc_text_size(const wxString &text,
return size;
}
float ImGuiWrapper::find_widest_text(std::vector<wxString> &text_list)
{
float width = .0f;
for(const wxString &text : text_list) {
width = std::max(width, this->calc_text_size(text).x);
}
return width;
}
ImVec2 ImGuiWrapper::calc_button_size(const wxString &text, const ImVec2 &button_size) const
{
const ImVec2 text_size = this->calc_text_size(text);
@ -1598,9 +1607,9 @@ bool begin_menu(const char *label, bool enabled)
return menu_is_open;
}
void end_menu()
{
ImGui::EndMenu();
void end_menu()
{
ImGui::EndMenu();
}
bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_size /* = ImVec2(0, 0)*/, ImU32 icon_color /* = 0*/, bool selected /* = false*/, bool enabled /* = true*/, bool* hovered/* = nullptr*/)

View file

@ -107,7 +107,7 @@ public:
static ImVec2 calc_text_size(const std::string& text, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
static ImVec2 calc_text_size(const wxString &text, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
ImVec2 calc_button_size(const wxString &text, const ImVec2 &button_size = ImVec2(0, 0)) const;
float find_widest_text(std::vector<wxString> &text_list);
ImVec2 get_item_spacing() const;
float get_slider_float_height() const;
const LastSliderStatus& get_last_slider_status() const { return m_last_slider_status; }

View file

@ -269,7 +269,16 @@ void PrintJob::process(Ctl &ctl)
auto model_name = model_info->metadata_items.find(BBL_DESIGNER_MODEL_TITLE_TAG);
if (model_name != model_info->metadata_items.end()) {
try {
params.project_name = model_name->second;
std::string mall_model_name = model_name->second;
std::replace(mall_model_name.begin(), mall_model_name.end(), ' ', '_');
const char* unusable_symbols = "<>[]:/\\|?*\" ";
for (const char* symbol = unusable_symbols; *symbol != '\0'; ++symbol) {
std::replace(mall_model_name.begin(), mall_model_name.end(), *symbol, '_');
}
std::regex pattern("_+");
params.project_name = std::regex_replace(mall_model_name, pattern, "_");
}
catch (...) {}
}

View file

@ -304,10 +304,10 @@ void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float init
bbl_render_left_sign(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
render_left_sign(imgui);
render_text(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
render_close_button(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
m_minimize_b_visible = false;
if (m_multiline && m_lines_count > 3)
render_minimize_button(imgui, win_pos.x, win_pos.y);
render_close_button(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y); // ORCA draw it after minimize button since its position related to minimize button
}
imgui.end();

View file

@ -2724,7 +2724,7 @@ bool PartPlate::intersects(const BoundingBoxf3& bb) const
return print_volume.intersects(bb);
}
void PartPlate::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id, bool render_cali)
void PartPlate::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id, bool render_cali, bool show_grid)
{
glsafe(::glEnable(GL_DEPTH_TEST));
@ -2744,7 +2744,8 @@ void PartPlate::render(const Transform3d& view_matrix, const Transform3d& projec
render_exclude_area(force_background_color);
}
render_grid(bottom);
if (show_grid)
render_grid(bottom);
render_height_limit(mode);
@ -4781,7 +4782,7 @@ void PartPlateList::postprocess_arrange_polygon(arrangement::ArrangePolygon& arr
/*rendering related functions*/
//render
void PartPlateList::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali)
void PartPlateList::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali, bool show_grid)
{
const std::lock_guard<std::mutex> local_lock(m_plates_mutex);
std::vector<PartPlate*>::iterator it = m_plate_list.begin();
@ -4806,15 +4807,15 @@ void PartPlateList::render(const Transform3d& view_matrix, const Transform3d& pr
if (current_index == m_current_plate) {
PartPlate::HeightLimitMode height_mode = (only_current)?PartPlate::HEIGHT_LIMIT_NONE:m_height_limit_mode;
if (plate_hover_index == current_index)
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, plate_hover_action, render_cali);
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, plate_hover_action, render_cali, show_grid);
else
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, -1, render_cali);
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, -1, render_cali, show_grid);
}
else {
if (plate_hover_index == current_index)
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, plate_hover_action, render_cali);
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, plate_hover_action, render_cali, show_grid);
else
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, -1, render_cali);
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, -1, render_cali, show_grid);
}
}
}

View file

@ -363,7 +363,7 @@ public:
bool contains(const BoundingBoxf3& bb) const;
bool intersects(const BoundingBoxf3& bb) const;
void render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_body = false, bool force_background_color = false, HeightLimitMode mode = HEIGHT_LIMIT_NONE, int hover_id = -1, bool render_cali = false);
void render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_body = false, bool force_background_color = false, HeightLimitMode mode = HEIGHT_LIMIT_NONE, int hover_id = -1, bool render_cali = false, bool show_grid = true);
void set_selected();
void set_unselected();
@ -781,7 +781,7 @@ public:
/*rendering related functions*/
void on_change_color_mode(bool is_dark) { m_is_dark = is_dark; }
void render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current = false, bool only_body = false, int hover_id = -1, bool render_cali = false);
void render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current = false, bool only_body = false, int hover_id = -1, bool render_cali = false, bool show_grid = true);
void set_render_option(bool bedtype_texture, bool plate_settings);
void set_render_cali(bool value = true) { render_cali_logo = value; }
void register_raycasters_for_picking(GLCanvas3D& canvas)

View file

@ -1307,8 +1307,9 @@ void Sidebar::update_all_preset_comboboxes()
}
}
} else {
// Orca: combobox don't have the btDefault option, so we need to -1
m_bed_type_list->SelectAndNotify(btPEI - 1);
// m_bed_type_list->SelectAndNotify(btPEI - 1);
BedType bed_type = preset_bundle.printers.get_edited_preset().get_default_bed_type(&preset_bundle);
m_bed_type_list->SelectAndNotify((int) bed_type - 1);
m_bed_type_list->Disable();
}
@ -9737,6 +9738,8 @@ auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config
_obj->config.set_key_value("wall_loops", new ConfigOptionInt(1));
_obj->config.set_key_value("only_one_wall_top", new ConfigOptionBool(true));
_obj->config.set_key_value("thick_internal_bridges", new ConfigOptionBool(false));
_obj->config.set_key_value("enable_extra_bridge_layer", new ConfigOptionEnum<EnableExtraBridgeLayer>(eblDisabled));
_obj->config.set_key_value("internal_bridge_density", new ConfigOptionPercent(100));
_obj->config.set_key_value("sparse_infill_density", new ConfigOptionPercent(35));
_obj->config.set_key_value("min_width_top_surface", new ConfigOptionFloatOrPercent(100,true));
_obj->config.set_key_value("bottom_shell_layers", new ConfigOptionInt(2));
@ -12658,38 +12661,58 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool us
}
}
auto config = get_app_config();
PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups, storage_paths, storage_names, config->get_bool("open_device_tab_post_upload"));
if (dlg.ShowModal() == wxID_OK) {
config->set_bool("open_device_tab_post_upload", dlg.switch_to_device_tab());
upload_job.switch_to_device_tab = dlg.switch_to_device_tab();
upload_job.upload_data.upload_path = dlg.filename();
upload_job.upload_data.post_action = dlg.post_action();
upload_job.upload_data.group = dlg.group();
upload_job.upload_data.storage = dlg.storage();
{
auto preset_bundle = wxGetApp().preset_bundle;
const auto opt = physical_printer_config->option<ConfigOptionEnum<PrintHostType>>("host_type");
const auto host_type = opt != nullptr ? opt->value : htElegooLink;
auto config = get_app_config();
// Show "Is printer clean" dialog for PrusaConnect - Upload and print.
if (std::string(upload_job.printhost->get_name()) == "PrusaConnect" && upload_job.upload_data.post_action == PrintHostPostUploadAction::StartPrint) {
GUI::MessageDialog dlg(nullptr, _L("Is the printer ready? Is the print sheet in place, empty and clean?"), _L("Upload and Print"), wxOK | wxCANCEL);
if (dlg.ShowModal() != wxID_OK)
return;
std::unique_ptr<PrintHostSendDialog> pDlg;
if (host_type == htElegooLink) {
pDlg = std::make_unique<ElegooPrintHostSendDialog>(default_output_file, upload_job.printhost->get_post_upload_actions(), groups,
storage_paths, storage_names,
config->get_bool("open_device_tab_post_upload"));
} else {
pDlg = std::make_unique<PrintHostSendDialog>(default_output_file, upload_job.printhost->get_post_upload_actions(), groups,
storage_paths, storage_names, config->get_bool("open_device_tab_post_upload"));
}
if (use_3mf) {
// Process gcode
const int result = send_gcode(plate_idx, nullptr);
if (result < 0) {
wxString msg = _L("Abnormal print file data. Please slice again");
show_error(this, msg, false);
return;
}
upload_job.upload_data.source_path = p->m_print_job_data._3mf_path;
pDlg->init();
if (pDlg->ShowModal() != wxID_OK) {
return;
}
p->export_gcode(fs::path(), false, std::move(upload_job));
config->set_bool("open_device_tab_post_upload", pDlg->switch_to_device_tab());
// PrintHostUpload upload_data;
upload_job.switch_to_device_tab = pDlg->switch_to_device_tab();
upload_job.upload_data.upload_path = pDlg->filename();
upload_job.upload_data.post_action = pDlg->post_action();
upload_job.upload_data.group = pDlg->group();
upload_job.upload_data.storage = pDlg->storage();
upload_job.upload_data.extended_info = pDlg->extendedInfo();
}
// Show "Is printer clean" dialog for PrusaConnect - Upload and print.
if (std::string(upload_job.printhost->get_name()) == "PrusaConnect" && upload_job.upload_data.post_action == PrintHostPostUploadAction::StartPrint) {
GUI::MessageDialog dlg(nullptr, _L("Is the printer ready? Is the print sheet in place, empty and clean?"), _L("Upload and Print"), wxOK | wxCANCEL);
if (dlg.ShowModal() != wxID_OK)
return;
}
if (use_3mf) {
// Process gcode
const int result = send_gcode(plate_idx, nullptr);
if (result < 0) {
wxString msg = _L("Abnormal print file data. Please slice again");
show_error(this, msg, false);
return;
}
upload_job.upload_data.source_path = p->m_print_job_data._3mf_path;
}
p->export_gcode(fs::path(), false, std::move(upload_job));
}
int Plater::send_gcode(int plate_idx, Export3mfProgressFn proFn)
{

View file

@ -47,11 +47,22 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo
, post_upload_action(PrintHostPostUploadAction::None)
, m_paths(storage_paths)
, m_switch_to_device_tab(switch_to_device_tab)
, m_path(path)
, m_post_actions(post_actions)
, m_storage_names(storage_names)
{
#ifdef __APPLE__
txt_filename->OSXDisableAllSmartSubstitutions();
#endif
const AppConfig *app_config = wxGetApp().app_config;
}
void PrintHostSendDialog::init()
{
const auto& path = m_path;
const auto& storage_paths = m_paths;
const auto& post_actions = m_post_actions;
const auto& storage_names = m_storage_names;
const AppConfig* app_config = wxGetApp().app_config;
auto *label_dir_hint = new wxStaticText(this, wxID_ANY, _L("Use forward slashes ( / ) as a directory separator if needed."));
label_dir_hint->Wrap(CONTENT_WIDTH * wxGetApp().em_unit());
@ -614,4 +625,331 @@ bool PrintHostQueueDialog::load_user_data(int udt, std::vector<int>& vector)
}
return true;
}
ElegooPrintHostSendDialog::ElegooPrintHostSendDialog(const fs::path& path,
PrintHostPostUploadActions post_actions,
const wxArrayString& groups,
const wxArrayString& storage_paths,
const wxArrayString& storage_names,
bool switch_to_device_tab)
: PrintHostSendDialog(path, post_actions, groups, storage_paths, storage_names, switch_to_device_tab)
, m_timeLapse(0)
, m_heatedBedLeveling(0)
, m_BedType(BedType::btPTE)
{}
void ElegooPrintHostSendDialog::init() {
auto preset_bundle = wxGetApp().preset_bundle;
auto model_id = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
if (!(model_id == "Elegoo-CC" || model_id == "Elegoo-C")) {
PrintHostSendDialog::init();
return;
}
const auto& path = m_path;
const auto& storage_paths = m_paths;
const auto& post_actions = m_post_actions;
const auto& storage_names = m_storage_names;
this->SetMinSize(wxSize(500, 300));
const AppConfig* app_config = wxGetApp().app_config;
std::string uploadAndPrint = app_config->get("recent", CONFIG_KEY_UPLOADANDPRINT);
if (!uploadAndPrint.empty())
post_upload_action = static_cast<PrintHostPostUploadAction>(std::stoi(uploadAndPrint));
std::string timeLapse = app_config->get("recent", CONFIG_KEY_TIMELAPSE);
if (!timeLapse.empty())
m_timeLapse = std::stoi(timeLapse);
std::string heatedBedLeveling = app_config->get("recent", CONFIG_KEY_HEATEDBEDLEVELING);
if (!heatedBedLeveling.empty())
m_heatedBedLeveling = std::stoi(heatedBedLeveling);
std::string bedType = app_config->get("recent", CONFIG_KEY_BEDTYPE);
if (!bedType.empty())
m_BedType = static_cast<BedType>(std::stoi(bedType));
auto* label_dir_hint = new wxStaticText(this, wxID_ANY, _L("Use forward slashes ( / ) as a directory separator if needed."));
label_dir_hint->Wrap(CONTENT_WIDTH * wxGetApp().em_unit());
wxSizerFlags flags = wxSizerFlags().Border(wxRIGHT, 16).Expand();
content_sizer->Add(txt_filename, flags);
content_sizer->AddSpacer(4);
content_sizer->Add(label_dir_hint);
content_sizer->AddSpacer(VERT_SPACING);
if (combo_groups != nullptr) {
// Repetier specific: Show a selection of file groups.
auto* label_group = new wxStaticText(this, wxID_ANY, _L("Group"));
content_sizer->Add(label_group);
content_sizer->Add(combo_groups, 0, wxBOTTOM, 2 * VERT_SPACING);
wxString recent_group = from_u8(app_config->get("recent", CONFIG_KEY_GROUP));
if (!recent_group.empty())
combo_groups->SetValue(recent_group);
}
if (combo_storage != nullptr) {
// PrusaLink specific: User needs to choose a storage
auto* label_group = new wxStaticText(this, wxID_ANY, _L("Upload to storage") + ":");
content_sizer->Add(label_group);
content_sizer->Add(combo_storage, 0, wxBOTTOM, 2 * VERT_SPACING);
combo_storage->SetValue(storage_names.front());
wxString recent_storage = from_u8(app_config->get("recent", CONFIG_KEY_STORAGE));
if (!recent_storage.empty())
combo_storage->SetValue(recent_storage);
} else if (storage_names.GetCount() == 1) {
// PrusaLink specific: Show which storage has been detected.
auto* label_group = new wxStaticText(this, wxID_ANY, _L("Upload to storage") + ": " + storage_names.front());
content_sizer->Add(label_group);
m_preselected_storage = m_paths.front();
}
wxString recent_path = from_u8(app_config->get("recent", CONFIG_KEY_PATH));
if (recent_path.Length() > 0 && recent_path[recent_path.Length() - 1] != '/') {
recent_path += '/';
}
const auto recent_path_len = recent_path.Length();
recent_path += path.filename().wstring();
wxString stem(path.stem().wstring());
const auto stem_len = stem.Length();
txt_filename->SetValue(recent_path);
{
auto checkbox_sizer = new wxBoxSizer(wxHORIZONTAL);
auto checkbox = new ::CheckBox(this, wxID_APPLY);
checkbox->SetValue(m_switch_to_device_tab);
checkbox->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& e) {
m_switch_to_device_tab = e.IsChecked();
e.Skip();
});
checkbox_sizer->Add(checkbox, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
auto checkbox_text = new wxStaticText(this, wxID_ANY, _L("Switch to Device tab after upload."), wxDefaultPosition, wxDefaultSize, 0);
checkbox_sizer->Add(checkbox_text, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
checkbox_text->SetFont(::Label::Body_13);
checkbox_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3D")));
content_sizer->Add(checkbox_sizer);
content_sizer->AddSpacer(VERT_SPACING);
}
warning_text = new wxStaticText(this, wxID_ANY,
_L("The selected bed type does not match the file. Please confirm before starting the print."),
wxDefaultPosition, wxDefaultSize, 0);
uploadandprint_sizer = new wxBoxSizer(wxVERTICAL);
{
auto checkbox_sizer = new wxBoxSizer(wxHORIZONTAL);
auto checkbox = new ::CheckBox(this);
checkbox->SetValue(post_upload_action == PrintHostPostUploadAction::StartPrint);
checkbox->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& e) {
if (e.IsChecked()) {
post_upload_action = PrintHostPostUploadAction::StartPrint;
} else {
post_upload_action = PrintHostPostUploadAction::None;
}
refresh();
e.Skip();
});
checkbox_sizer->Add(checkbox, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
auto checkbox_text = new wxStaticText(this, wxID_ANY, _L("Upload and Print"), wxDefaultPosition, wxDefaultSize, 0);
checkbox_sizer->Add(checkbox_text, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
checkbox_text->SetFont(::Label::Body_13);
checkbox_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3D")));
content_sizer->Add(checkbox_sizer);
content_sizer->AddSpacer(VERT_SPACING);
}
{
auto checkbox_sizer = new wxBoxSizer(wxHORIZONTAL);
auto checkbox = new ::CheckBox(this);
checkbox->SetValue(m_timeLapse == 1);
checkbox->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& e) {
m_timeLapse = e.IsChecked() ? 1 : 0;
e.Skip();
});
checkbox_sizer->AddSpacer(16);
checkbox_sizer->Add(checkbox, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
auto checkbox_text = new wxStaticText(this, wxID_ANY, _L("Time-lapse"), wxDefaultPosition, wxDefaultSize, 0);
checkbox_sizer->Add(checkbox_text, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
checkbox_text->SetFont(::Label::Body_13);
checkbox_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3D")));
uploadandprint_sizer->Add(checkbox_sizer);
uploadandprint_sizer->AddSpacer(VERT_SPACING);
}
{
auto checkbox_sizer = new wxBoxSizer(wxHORIZONTAL);
auto checkbox = new ::CheckBox(this);
checkbox->SetValue(m_heatedBedLeveling == 1);
checkbox->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& e) {
m_heatedBedLeveling = e.IsChecked() ? 1 : 0;
e.Skip();
});
checkbox_sizer->AddSpacer(16);
checkbox_sizer->Add(checkbox, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
auto checkbox_text = new wxStaticText(this, wxID_ANY, _L("Heated Bed Leveling"), wxDefaultPosition, wxDefaultSize, 0);
checkbox_sizer->Add(checkbox_text, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
checkbox_text->SetFont(::Label::Body_13);
checkbox_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3D")));
uploadandprint_sizer->Add(checkbox_sizer);
uploadandprint_sizer->AddSpacer(VERT_SPACING);
}
{
auto radioBoxA = new ::RadioBox(this);
auto radioBoxB = new ::RadioBox(this);
if (m_BedType == BedType::btPC)
radioBoxB->SetValue(true);
else
radioBoxA->SetValue(true);
radioBoxA->Bind(wxEVT_LEFT_DOWN, [this, radioBoxA, radioBoxB](wxMouseEvent& e) {
radioBoxA->SetValue(true);
radioBoxB->SetValue(false);
m_BedType = BedType::btPTE;
refresh();
});
radioBoxB->Bind(wxEVT_LEFT_DOWN, [this, radioBoxA, radioBoxB](wxMouseEvent& e) {
radioBoxA->SetValue(false);
radioBoxB->SetValue(true);
m_BedType = BedType::btPC;
refresh();
});
{
auto radio_sizer = new wxBoxSizer(wxHORIZONTAL);
radio_sizer->AddSpacer(16);
radio_sizer->Add(radioBoxA, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
auto checkbox_text = new wxStaticText(this, wxID_ANY, _L("Textured Build Plate (Side A)"), wxDefaultPosition, wxDefaultSize, 0);
radio_sizer->Add(checkbox_text, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
checkbox_text->SetFont(::Label::Body_13);
checkbox_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3D")));
uploadandprint_sizer->Add(radio_sizer);
uploadandprint_sizer->AddSpacer(VERT_SPACING);
}
{
auto radio_sizer = new wxBoxSizer(wxHORIZONTAL);
radio_sizer->AddSpacer(16);
radio_sizer->Add(radioBoxB, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
auto checkbox_text = new wxStaticText(this, wxID_ANY, _L("Smooth Build Plate (Side B)"), wxDefaultPosition, wxDefaultSize, 0);
radio_sizer->Add(checkbox_text, 0, wxALL | wxALIGN_CENTER, FromDIP(2));
checkbox_text->SetFont(::Label::Body_13);
checkbox_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3D")));
uploadandprint_sizer->Add(radio_sizer);
uploadandprint_sizer->AddSpacer(VERT_SPACING);
}
}
{
auto h_sizer = new wxBoxSizer(wxHORIZONTAL);
warning_text->SetFont(::Label::Body_13);
warning_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#FF1001")));
// wrapping the text
warning_text->Wrap(350);
h_sizer->AddSpacer(16);
h_sizer->Add(warning_text);
uploadandprint_sizer->Add(h_sizer);
uploadandprint_sizer->AddSpacer(VERT_SPACING);
}
content_sizer->Add(uploadandprint_sizer);
uploadandprint_sizer->Show(post_upload_action == PrintHostPostUploadAction::StartPrint);
warning_text->Show(post_upload_action == PrintHostPostUploadAction::StartPrint && appBedType() != m_BedType);
uploadandprint_sizer->Layout();
if (size_t extension_start = recent_path.find_last_of('.'); extension_start != std::string::npos)
m_valid_suffix = recent_path.substr(extension_start);
// .gcode suffix control
auto validate_path = [this](const wxString& path) -> bool {
if (!path.Lower().EndsWith(m_valid_suffix.Lower())) {
MessageDialog msg_wingow(this,
wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"),
m_valid_suffix),
wxString(SLIC3R_APP_NAME), wxYES | wxNO);
if (msg_wingow.ShowModal() == wxID_NO)
return false;
}
return true;
};
auto* btn_ok = add_button(wxID_OK, true, _L("Upload"));
btn_ok->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) {
if (validate_path(txt_filename->GetValue())) {
// post_upload_action = PrintHostPostUploadAction::None;
EndDialog(wxID_OK);
}
});
txt_filename->SetFocus();
add_button(wxID_CANCEL, false, _L("Cancel"));
finalize();
#ifdef __linux__
// On Linux with GTK2 when text control lose the focus then selection (colored background) disappears but text color stay white
// and as a result the text is invisible with light mode
// see https://github.com/prusa3d/PrusaSlicer/issues/4532
// Workaround: Unselect text selection explicitly on kill focus
txt_filename->Bind(
wxEVT_KILL_FOCUS,
[this](wxEvent& e) {
e.Skip();
txt_filename->SetInsertionPoint(txt_filename->GetLastPosition());
},
txt_filename->GetId());
#endif /* __linux__ */
Bind(wxEVT_SHOW, [=](const wxShowEvent&) {
// Another similar case where the function only works with EVT_SHOW + CallAfter,
// this time on Mac.
CallAfter([=]() {
txt_filename->SetInsertionPoint(0);
txt_filename->SetSelection(recent_path_len, recent_path_len + stem_len);
});
});
}
void ElegooPrintHostSendDialog::EndModal(int ret)
{
if (ret == wxID_OK) {
AppConfig* app_config = wxGetApp().app_config;
app_config->set("recent", CONFIG_KEY_UPLOADANDPRINT, std::to_string(static_cast<int>(post_upload_action)));
app_config->set("recent", CONFIG_KEY_TIMELAPSE, std::to_string(m_timeLapse));
app_config->set("recent", CONFIG_KEY_HEATEDBEDLEVELING, std::to_string(m_heatedBedLeveling));
app_config->set("recent", CONFIG_KEY_BEDTYPE, std::to_string(static_cast<int>(m_BedType)));
}
PrintHostSendDialog::EndModal(ret);
}
BedType ElegooPrintHostSendDialog::appBedType() const
{
std::string str_bed_type = wxGetApp().app_config->get("curr_bed_type");
int bed_type_value = atoi(str_bed_type.c_str());
return static_cast<BedType>(bed_type_value);
}
void ElegooPrintHostSendDialog::refresh()
{
if (uploadandprint_sizer) {
if (post_upload_action == PrintHostPostUploadAction::StartPrint) {
uploadandprint_sizer->Show(true);
} else {
uploadandprint_sizer->Show(false);
}
}
if (warning_text) {
warning_text->Show(post_upload_action == PrintHostPostUploadAction::StartPrint && appBedType() != m_BedType);
}
this->Layout();
this->Fit();
}
}}

View file

@ -12,7 +12,7 @@
#include "GUI_Utils.hpp"
#include "MsgDialog.hpp"
#include "../Utils/PrintHost.hpp"
#include "libslic3r/PrintConfig.hpp"
class wxButton;
class wxTextCtrl;
class wxChoice;
@ -27,6 +27,7 @@ class PrintHostSendDialog : public GUI::MsgDialog
{
public:
PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups, const wxArrayString& storage_paths, const wxArrayString& storage_names, bool switch_to_device_tab);
virtual ~PrintHostSendDialog() {}
boost::filesystem::path filename() const;
PrintHostPostUploadAction post_action() const;
std::string group() const;
@ -34,7 +35,10 @@ public:
bool switch_to_device_tab() const {return m_switch_to_device_tab;}
virtual void EndModal(int ret) override;
private:
virtual void init();
virtual std::map<std::string, std::string> extendedInfo() const { return {}; }
protected:
wxTextCtrl *txt_filename;
wxComboBox *combo_groups;
wxComboBox* combo_storage;
@ -43,6 +47,10 @@ private:
wxString m_preselected_storage;
wxArrayString m_paths;
bool m_switch_to_device_tab;
boost::filesystem::path m_path;
PrintHostPostUploadActions m_post_actions;
wxArrayString m_storage_names;
};
@ -131,6 +139,47 @@ private:
bool load_user_data(int, std::vector<int>&);
};
class ElegooPrintHostSendDialog : public PrintHostSendDialog
{
public:
ElegooPrintHostSendDialog(const boost::filesystem::path& path,
PrintHostPostUploadActions post_actions,
const wxArrayString& groups,
const wxArrayString& storage_paths,
const wxArrayString& storage_names,
bool switch_to_device_tab);
virtual void EndModal(int ret) override;
int timeLapse() const { return m_timeLapse; }
int heatedBedLeveling() const { return m_heatedBedLeveling; }
BedType bedType() const { return m_BedType; }
virtual void init() override;
virtual std::map<std::string, std::string> extendedInfo() const
{
return {{"bedType", std::to_string(static_cast<int>(m_BedType))},
{"timeLapse", std::to_string(m_timeLapse)},
{"heatedBedLeveling", std::to_string(m_heatedBedLeveling)}};
}
private:
BedType appBedType() const;
void refresh();
const char* CONFIG_KEY_UPLOADANDPRINT = "elegoolink_upload_and_print";
const char* CONFIG_KEY_TIMELAPSE = "elegoolink_timelapse";
const char* CONFIG_KEY_HEATEDBEDLEVELING = "elegoolink_heated_bed_leveling";
const char* CONFIG_KEY_BEDTYPE = "elegoolink_bed_type";
private:
wxStaticText* warning_text{nullptr};
wxBoxSizer* uploadandprint_sizer{nullptr};
int m_timeLapse;
int m_heatedBedLeveling;
BedType m_BedType;
};
wxDECLARE_EVENT(EVT_PRINTHOST_PROGRESS, PrintHostQueueDialog::Event);
wxDECLARE_EVENT(EVT_PRINTHOST_ERROR, PrintHostQueueDialog::Event);
wxDECLARE_EVENT(EVT_PRINTHOST_CANCEL, PrintHostQueueDialog::Event);

View file

@ -2077,6 +2077,7 @@ void Selection::copy_to_clipboard()
dst_object->sla_support_points = src_object->sla_support_points;
dst_object->sla_points_status = src_object->sla_points_status;
dst_object->sla_drain_holes = src_object->sla_drain_holes;
dst_object->brim_points = src_object->brim_points;
dst_object->layer_config_ranges = src_object->layer_config_ranges; // #ys_FIXME_experiment
dst_object->layer_height_profile.assign(src_object->layer_height_profile);
dst_object->origin_translation = src_object->origin_translation;

View file

@ -1665,6 +1665,13 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
}
//Orca: disable purge_in_prime_tower if single_extruder_multi_material is disabled
if (opt_key == "single_extruder_multi_material" && m_config->opt_bool("single_extruder_multi_material") == false){
DynamicPrintConfig new_conf = *m_config;
new_conf.set_key_value("purge_in_prime_tower", new ConfigOptionBool(false));
m_config_manipulation.apply(m_config, &new_conf);
}
if (m_postpone_update_ui) {
// It means that not all values are rolled to the system/last saved values jet.
// And call of the update() can causes a redundant check of the config values,
@ -2105,8 +2112,10 @@ void TabPrint::build()
optgroup->append_single_option_line("bridge_flow");
optgroup->append_single_option_line("internal_bridge_flow");
optgroup->append_single_option_line("bridge_density");
optgroup->append_single_option_line("internal_bridge_density");
optgroup->append_single_option_line("thick_bridges");
optgroup->append_single_option_line("thick_internal_bridges");
optgroup->append_single_option_line("enable_extra_bridge_layer");
optgroup->append_single_option_line("dont_filter_internal_bridges");
optgroup->append_single_option_line("counterbore_hole_bridging","counterbore-hole-bridging");
@ -2138,6 +2147,8 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Infill"), L"param_infill");
optgroup->append_single_option_line("sparse_infill_density");
optgroup->append_single_option_line("sparse_infill_pattern", "fill-patterns#infill types and their properties of sparse");
optgroup->append_single_option_line("lattice_angle_1");
optgroup->append_single_option_line("lattice_angle_2");
optgroup->append_single_option_line("infill_anchor_max");
optgroup->append_single_option_line("infill_anchor");
optgroup->append_single_option_line("internal_solid_infill_pattern");
@ -2317,6 +2328,7 @@ void TabPrint::build()
optgroup->append_single_option_line("flush_into_support", "reduce-wasting-during-filament-change#wipe-into-support-enabled-by-default");
optgroup = page->new_optgroup(L("Advanced"), L"advanced");
optgroup->append_single_option_line("interlocking_beam");
optgroup->append_single_option_line("interface_shells");
optgroup->append_single_option_line("mmu_segmented_region_max_width");
optgroup->append_single_option_line("mmu_segmented_region_interlocking_depth");
optgroup->append_single_option_line("interlocking_beam_width");
@ -2350,6 +2362,9 @@ page = add_options_page(L("Others"), "custom-gcode_other"); // ORCA: icon only v
optgroup->append_single_option_line("spiral_mode", "spiral-vase");
optgroup->append_single_option_line("spiral_mode_smooth", "spiral-vase#smooth");
optgroup->append_single_option_line("spiral_mode_max_xy_smoothing", "spiral-vase#max-xy-smoothing");
optgroup->append_single_option_line("spiral_starting_flow_ratio", "spiral-vase#starting-flow-ratio");
optgroup->append_single_option_line("spiral_finishing_flow_ratio", "spiral-vase#finishing-flow-ratio");
optgroup->append_single_option_line("timelapse_type", "Timelapse");
optgroup->append_single_option_line("fuzzy_skin");
@ -2387,18 +2402,19 @@ page = add_options_page(L("Others"), "custom-gcode_other"); // ORCA: icon only v
option.opt.height = 25;//250;
optgroup->append_single_option_line(option);
page = add_options_page(L("Dependencies"), "custom-gcode_advanced");
optgroup = page->new_optgroup(L("Profile dependencies"));
// Orca: hide the dependencies tab for process for now. The UI is not ready yet.
// page = add_options_page(L("Dependencies"), "custom-gcode_advanced");
// optgroup = page->new_optgroup(L("Profile dependencies"));
create_line_with_widget(optgroup.get(), "compatible_printers", "", [this](wxWindow* parent) {
return compatible_widget_create(parent, m_compatible_printers);
});
// create_line_with_widget(optgroup.get(), "compatible_printers", "", [this](wxWindow* parent) {
// return compatible_widget_create(parent, m_compatible_printers);
// });
option = optgroup->get_option("compatible_printers_condition");
option.opt.full_width = true;
optgroup->append_single_option_line(option);
// option = optgroup->get_option("compatible_printers_condition");
// option.opt.full_width = true;
// optgroup->append_single_option_line(option);
build_preset_description_line(optgroup.get());
// build_preset_description_line(optgroup.get());
}
// Reload current config (aka presets->edited_preset->config) into the UI fields.
@ -3620,13 +3636,29 @@ void TabFilament::toggle_options()
{
bool pa = m_config->opt_bool("enable_pressure_advance", 0);
toggle_option("pressure_advance", pa);
// Orca: Enable the plates that should be visible when multi bed support is enabled or a BBL printer is selected
auto support_multi_bed_types = is_BBL_printer || cfg.opt_bool("support_multi_bed_types");
toggle_line("supertack_plate_temp_initial_layer", support_multi_bed_types );
toggle_line("cool_plate_temp_initial_layer", support_multi_bed_types );
toggle_line("textured_cool_plate_temp_initial_layer", support_multi_bed_types);
toggle_line("eng_plate_temp_initial_layer", support_multi_bed_types);
toggle_line("textured_plate_temp_initial_layer", support_multi_bed_types);
//Orca: Enable the plates that should be visible when multi bed support is enabled or a BBL printer is selected; otherwise, enable only the plate visible for the selected bed type.
DynamicConfig& proj_cfg = m_preset_bundle->project_config;
std::string bed_temp_1st_layer_key = "";
if (proj_cfg.has("curr_bed_type"))
{
bed_temp_1st_layer_key = get_bed_temp_1st_layer_key(proj_cfg.opt_enum<BedType>("curr_bed_type"));
}
const std::vector<std::string> bed_temp_keys = {"supertack_plate_temp_initial_layer", "cool_plate_temp_initial_layer",
"textured_cool_plate_temp_initial_layer", "eng_plate_temp_initial_layer",
"textured_plate_temp_initial_layer", "hot_plate_temp_initial_layer"};
bool support_multi_bed_types = std::find(bed_temp_keys.begin(), bed_temp_keys.end(), bed_temp_1st_layer_key) ==
bed_temp_keys.end() ||
is_BBL_printer || cfg.opt_bool("support_multi_bed_types");
for (const auto& key : bed_temp_keys)
{
toggle_line(key, support_multi_bed_types || bed_temp_1st_layer_key == key);
}
// Orca: adaptive pressure advance and calibration model
// If PA is not enabled, disable adaptive pressure advance and hide the model section