mirror of
https://github.com/QIDITECH/QIDISlicer.git
synced 2026-02-02 00:48:43 +03:00
Merge prusa 2.6.1
This commit is contained in:
@@ -1059,94 +1059,6 @@ wxDEFINE_EVENT(EVT_GLCANVAS_GIZMO_HIGHLIGHTER_TIMER, wxTimerEvent);
|
||||
|
||||
const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25;
|
||||
|
||||
void GLCanvas3D::load_arrange_settings()
|
||||
{
|
||||
std::string dist_fff_str =
|
||||
wxGetApp().app_config->get("arrange", "min_object_distance_fff");
|
||||
|
||||
std::string dist_bed_fff_str =
|
||||
wxGetApp().app_config->get("arrange", "min_bed_distance_fff");
|
||||
|
||||
std::string dist_fff_seq_print_str =
|
||||
wxGetApp().app_config->get("arrange", "min_object_distance_fff_seq_print");
|
||||
|
||||
std::string dist_bed_fff_seq_print_str =
|
||||
wxGetApp().app_config->get("arrange", "min_bed_distance_fff_seq_print");
|
||||
|
||||
std::string dist_sla_str =
|
||||
wxGetApp().app_config->get("arrange", "min_object_distance_sla");
|
||||
|
||||
std::string dist_bed_sla_str =
|
||||
wxGetApp().app_config->get("arrange", "min_bed_distance_sla");
|
||||
|
||||
std::string en_rot_fff_str =
|
||||
wxGetApp().app_config->get("arrange", "enable_rotation_fff");
|
||||
|
||||
std::string en_rot_fff_seqp_str =
|
||||
wxGetApp().app_config->get("arrange", "enable_rotation_fff_seq_print");
|
||||
|
||||
std::string en_rot_sla_str =
|
||||
wxGetApp().app_config->get("arrange", "enable_rotation_sla");
|
||||
|
||||
// std::string alignment_fff_str =
|
||||
// wxGetApp().app_config->get("arrange", "alignment_fff");
|
||||
|
||||
// std::string alignment_fff_seqp_str =
|
||||
// wxGetApp().app_config->get("arrange", "alignment_fff_seq_pring");
|
||||
|
||||
// std::string alignment_sla_str =
|
||||
// wxGetApp().app_config->get("arrange", "alignment_sla");
|
||||
|
||||
// Override default alignment and save save/load it to a temporary slot "alignment_xl"
|
||||
std::string alignment_xl_str =
|
||||
wxGetApp().app_config->get("arrange", "alignment_xl");
|
||||
|
||||
if (!dist_fff_str.empty())
|
||||
m_arrange_settings_fff.distance = string_to_float_decimal_point(dist_fff_str);
|
||||
|
||||
if (!dist_bed_fff_str.empty())
|
||||
m_arrange_settings_fff.distance_from_bed = string_to_float_decimal_point(dist_bed_fff_str);
|
||||
|
||||
if (!dist_fff_seq_print_str.empty())
|
||||
m_arrange_settings_fff_seq_print.distance = string_to_float_decimal_point(dist_fff_seq_print_str);
|
||||
|
||||
if (!dist_bed_fff_seq_print_str.empty())
|
||||
m_arrange_settings_fff_seq_print.distance_from_bed = string_to_float_decimal_point(dist_bed_fff_seq_print_str);
|
||||
|
||||
if (!dist_sla_str.empty())
|
||||
m_arrange_settings_sla.distance = string_to_float_decimal_point(dist_sla_str);
|
||||
|
||||
if (!dist_bed_sla_str.empty())
|
||||
m_arrange_settings_sla.distance_from_bed = string_to_float_decimal_point(dist_bed_sla_str);
|
||||
|
||||
if (!en_rot_fff_str.empty())
|
||||
m_arrange_settings_fff.enable_rotation = (en_rot_fff_str == "1" || en_rot_fff_str == "yes");
|
||||
|
||||
if (!en_rot_fff_seqp_str.empty())
|
||||
m_arrange_settings_fff_seq_print.enable_rotation = (en_rot_fff_seqp_str == "1" || en_rot_fff_seqp_str == "yes");
|
||||
|
||||
if (!en_rot_sla_str.empty())
|
||||
m_arrange_settings_sla.enable_rotation = (en_rot_sla_str == "1" || en_rot_sla_str == "yes");
|
||||
|
||||
// if (!alignment_sla_str.empty())
|
||||
// m_arrange_settings_sla.alignment = std::stoi(alignment_sla_str);
|
||||
|
||||
// if (!alignment_fff_str.empty())
|
||||
// m_arrange_settings_fff.alignment = std::stoi(alignment_fff_str);
|
||||
|
||||
// if (!alignment_fff_seqp_str.empty())
|
||||
// m_arrange_settings_fff_seq_print.alignment = std::stoi(alignment_fff_seqp_str);
|
||||
|
||||
// Override default alignment and save save/load it to a temporary slot "alignment_xl"
|
||||
int arr_alignment = static_cast<int>(arrangement::Pivots::BottomLeft);
|
||||
if (!alignment_xl_str.empty())
|
||||
arr_alignment = std::stoi(alignment_xl_str);
|
||||
|
||||
m_arrange_settings_sla.alignment = arr_alignment ;
|
||||
m_arrange_settings_fff.alignment = arr_alignment ;
|
||||
m_arrange_settings_fff_seq_print.alignment = arr_alignment ;
|
||||
}
|
||||
|
||||
static std::vector<int> processed_objects_idxs(const Model& model, const SLAPrint& sla_print, const GLVolumePtrs& volumes)
|
||||
{
|
||||
std::vector<int> ret;
|
||||
@@ -1399,46 +1311,50 @@ void GLCanvas3D::SLAView::select_full_instance(const GLVolume::CompositeID& id)
|
||||
|
||||
PrinterTechnology GLCanvas3D::current_printer_technology() const
|
||||
{
|
||||
return m_process->current_printer_technology();
|
||||
return m_process ? m_process->current_printer_technology() : ptFFF;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::is_arrange_alignment_enabled() const
|
||||
{
|
||||
return m_config ? is_XL_printer(*m_config) : false;
|
||||
return m_config ? is_XL_printer(*m_config) && !this->get_wipe_tower_info() : false;
|
||||
}
|
||||
|
||||
GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
|
||||
: m_canvas(canvas)
|
||||
, m_context(nullptr)
|
||||
, m_bed(bed)
|
||||
GLCanvas3D::GLCanvas3D(wxGLCanvas *canvas, Bed3D &bed)
|
||||
: m_canvas(canvas),
|
||||
m_context(nullptr),
|
||||
m_bed(bed)
|
||||
#if ENABLE_RETINA_GL
|
||||
, m_retina_helper(nullptr)
|
||||
,
|
||||
m_retina_helper(nullptr)
|
||||
#endif
|
||||
, m_in_render(false)
|
||||
, m_main_toolbar(GLToolbar::Normal, "Main")
|
||||
, m_undoredo_toolbar(GLToolbar::Normal, "Undo_Redo")
|
||||
, m_gizmos(*this)
|
||||
, m_use_clipping_planes(false)
|
||||
, m_sidebar_field("")
|
||||
, m_extra_frame_requested(false)
|
||||
, m_config(nullptr)
|
||||
, m_process(nullptr)
|
||||
, m_model(nullptr)
|
||||
, m_dirty(true)
|
||||
, m_initialized(false)
|
||||
, m_apply_zoom_to_volumes_filter(false)
|
||||
, m_picking_enabled(false)
|
||||
, m_moving_enabled(false)
|
||||
, m_dynamic_background_enabled(false)
|
||||
, m_multisample_allowed(false)
|
||||
, m_moving(false)
|
||||
, m_tab_down(false)
|
||||
, m_cursor_type(Standard)
|
||||
, m_reload_delayed(false)
|
||||
, m_render_sla_auxiliaries(true)
|
||||
, m_labels(*this)
|
||||
, m_slope(m_volumes)
|
||||
, m_sla_view(*this)
|
||||
,
|
||||
m_in_render(false),
|
||||
m_main_toolbar(GLToolbar::Normal, "Main"),
|
||||
m_undoredo_toolbar(GLToolbar::Normal, "Undo_Redo"),
|
||||
m_gizmos(*this),
|
||||
m_use_clipping_planes(false),
|
||||
m_sidebar_field(""),
|
||||
m_extra_frame_requested(false),
|
||||
m_config(nullptr),
|
||||
m_process(nullptr),
|
||||
m_model(nullptr),
|
||||
m_dirty(true),
|
||||
m_initialized(false),
|
||||
m_apply_zoom_to_volumes_filter(false),
|
||||
m_picking_enabled(false),
|
||||
m_moving_enabled(false),
|
||||
m_dynamic_background_enabled(false),
|
||||
m_multisample_allowed(false),
|
||||
m_moving(false),
|
||||
m_tab_down(false),
|
||||
m_cursor_type(Standard),
|
||||
m_reload_delayed(false),
|
||||
m_render_sla_auxiliaries(true),
|
||||
m_labels(*this),
|
||||
m_slope(m_volumes),
|
||||
m_sla_view(*this),
|
||||
m_arrange_settings_db{wxGetApp().app_config},
|
||||
m_arrange_settings_dialog{wxGetApp().imgui(), &m_arrange_settings_db}
|
||||
{
|
||||
if (m_canvas != nullptr) {
|
||||
m_timer.SetOwner(m_canvas);
|
||||
@@ -1448,9 +1364,13 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
|
||||
#endif // ENABLE_RETINA_GL
|
||||
}
|
||||
|
||||
load_arrange_settings();
|
||||
|
||||
m_selection.set_volumes(&m_volumes.volumes);
|
||||
m_arrange_settings_dialog.show_xl_align_combo([this](){
|
||||
return this->is_arrange_alignment_enabled();
|
||||
});
|
||||
m_arrange_settings_dialog.on_arrange_btn([]{
|
||||
wxGetApp().plater()->arrange();
|
||||
});
|
||||
}
|
||||
|
||||
GLCanvas3D::~GLCanvas3D()
|
||||
@@ -1537,11 +1457,16 @@ ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state(bool sele
|
||||
{
|
||||
ModelInstanceEPrintVolumeState state = ModelInstanceEPrintVolumeState::ModelInstancePVS_Inside;
|
||||
if (m_initialized && !m_volumes.empty())
|
||||
check_volumes_outside_state(m_bed.build_volume(), &state, selection_only);
|
||||
check_volumes_outside_state(const_cast<GLVolumeCollection&>(m_volumes), &state, selection_only);
|
||||
return state;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::check_volumes_outside_state(const Slic3r::BuildVolume& build_volume, ModelInstanceEPrintVolumeState* out_state, bool selection_only) const
|
||||
void GLCanvas3D::check_volumes_outside_state(GLVolumeCollection& volumes) const
|
||||
{
|
||||
check_volumes_outside_state(volumes, nullptr, false);
|
||||
}
|
||||
|
||||
bool GLCanvas3D::check_volumes_outside_state(GLVolumeCollection& volumes, ModelInstanceEPrintVolumeState* out_state, bool selection_only) const
|
||||
{
|
||||
auto volume_below = [](GLVolume& volume) -> bool
|
||||
{ return volume.object_idx() != -1 && volume.volume_idx() != -1 && volume.is_below_printbed(); };
|
||||
@@ -1555,26 +1480,27 @@ bool GLCanvas3D::check_volumes_outside_state(const Slic3r::BuildVolume& build_vo
|
||||
auto volume_convex_mesh = [this, volume_sinking](GLVolume& volume) -> const TriangleMesh&
|
||||
{ return volume_sinking(volume) ? m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : *volume.convex_hull(); };
|
||||
|
||||
auto volumes_to_process_idxs = [this, selection_only]() {
|
||||
std::vector<unsigned int> ret;
|
||||
if (!selection_only || m_selection.is_empty()) {
|
||||
ret = std::vector<unsigned int>(m_volumes.volumes.size());
|
||||
std::iota(ret.begin(), ret.end(), 0);
|
||||
}
|
||||
else {
|
||||
const GUI::Selection::IndicesList& selected_volume_idxs = m_selection.get_volume_idxs();
|
||||
ret.assign(selected_volume_idxs.begin(), selected_volume_idxs.end());
|
||||
}
|
||||
return ret;
|
||||
auto volumes_to_process_idxs = [this, &volumes, selection_only]() {
|
||||
std::vector<unsigned int> ret;
|
||||
if (!selection_only || m_selection.is_empty()) {
|
||||
ret = std::vector<unsigned int>(volumes.volumes.size());
|
||||
std::iota(ret.begin(), ret.end(), 0);
|
||||
}
|
||||
else {
|
||||
const GUI::Selection::IndicesList& selected_volume_idxs = m_selection.get_volume_idxs();
|
||||
ret.assign(selected_volume_idxs.begin(), selected_volume_idxs.end());
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside;
|
||||
bool contained_min_one = false;
|
||||
|
||||
const std::vector<unsigned int> volumes_idxs = volumes_to_process_idxs();
|
||||
const Slic3r::BuildVolume& build_volume = m_bed.build_volume();
|
||||
|
||||
const std::vector<unsigned int> volumes_idxs = volumes_to_process_idxs();
|
||||
for (unsigned int vol_idx : volumes_idxs) {
|
||||
GLVolume* volume = m_volumes.volumes[vol_idx];
|
||||
GLVolume* volume = volumes.volumes[vol_idx];
|
||||
if (!volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (!volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) {
|
||||
BuildVolume::ObjectState state;
|
||||
if (volume_below(*volume))
|
||||
@@ -1587,7 +1513,7 @@ bool GLCanvas3D::check_volumes_outside_state(const Slic3r::BuildVolume& build_vo
|
||||
break;
|
||||
case BuildVolume::Type::Circle:
|
||||
case BuildVolume::Type::Convex:
|
||||
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
|
||||
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
|
||||
case BuildVolume::Type::Custom:
|
||||
state = build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast<float>(), volume_sinking(*volume));
|
||||
break;
|
||||
@@ -1609,9 +1535,9 @@ bool GLCanvas3D::check_volumes_outside_state(const Slic3r::BuildVolume& build_vo
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int vol_idx = 0; vol_idx < m_volumes.volumes.size(); ++vol_idx) {
|
||||
for (unsigned int vol_idx = 0; vol_idx < volumes.volumes.size(); ++vol_idx) {
|
||||
if (std::find(volumes_idxs.begin(), volumes_idxs.end(), vol_idx) == volumes_idxs.end()) {
|
||||
if (!m_volumes.volumes[vol_idx]->is_outside) {
|
||||
if (!volumes.volumes[vol_idx]->is_outside) {
|
||||
contained_min_one = true;
|
||||
break;
|
||||
}
|
||||
@@ -1717,6 +1643,30 @@ void GLCanvas3D::set_config(const DynamicPrintConfig* config)
|
||||
{
|
||||
m_config = config;
|
||||
m_layers_editing.set_config(config);
|
||||
|
||||
|
||||
if (config) {
|
||||
PrinterTechnology ptech = current_printer_technology();
|
||||
|
||||
auto slot = ArrangeSettingsDb_AppCfg::slotFFF;
|
||||
|
||||
if (ptech == ptSLA) {
|
||||
slot = ArrangeSettingsDb_AppCfg::slotSLA;
|
||||
} else if (ptech == ptFFF) {
|
||||
auto co_opt = config->option<ConfigOptionBool>("complete_objects");
|
||||
if (co_opt && co_opt->value)
|
||||
slot = ArrangeSettingsDb_AppCfg::slotFFFSeqPrint;
|
||||
else
|
||||
slot = ArrangeSettingsDb_AppCfg::slotFFF;
|
||||
}
|
||||
|
||||
m_arrange_settings_db.set_active_slot(slot);
|
||||
|
||||
double objdst = min_object_distance(*config);
|
||||
double min_obj_dst = slot == ArrangeSettingsDb_AppCfg::slotFFFSeqPrint ? objdst : 0.;
|
||||
m_arrange_settings_db.set_distance_from_obj_range(slot, min_obj_dst, 100.);
|
||||
m_arrange_settings_db.get_defaults(slot).d_obj = objdst;
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::set_process(BackgroundSlicingProcess *process)
|
||||
@@ -1984,7 +1934,7 @@ void GLCanvas3D::render()
|
||||
_render_bed_axes();
|
||||
if (is_looking_downward)
|
||||
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), false);
|
||||
if (!m_main_toolbar.is_enabled())
|
||||
if (!m_main_toolbar.is_enabled() && current_printer_technology() != ptSLA)
|
||||
_render_gcode();
|
||||
_render_objects(GLVolumeCollection::ERenderType::Transparent);
|
||||
|
||||
@@ -2621,6 +2571,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
update_object_list = true;
|
||||
}
|
||||
|
||||
// @Enrico suggest this solution to preven accessing pointer on caster without data
|
||||
m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Volume);
|
||||
m_gizmos.update_data();
|
||||
m_gizmos.refresh_on_off_state();
|
||||
|
||||
@@ -2631,7 +2583,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
// checks for geometry outside the print volume to render it accordingly
|
||||
if (!m_volumes.empty()) {
|
||||
ModelInstanceEPrintVolumeState state;
|
||||
const bool contained_min_one = check_volumes_outside_state(m_bed.build_volume(), &state, !force_full_scene_refresh);
|
||||
const bool contained_min_one = check_volumes_outside_state(m_volumes, &state, !force_full_scene_refresh);
|
||||
const bool partlyOut = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Partly_Outside);
|
||||
const bool fullyOut = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Fully_Outside);
|
||||
|
||||
@@ -2688,7 +2640,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
}
|
||||
|
||||
// refresh volume raycasters for picking
|
||||
m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Volume);
|
||||
for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
|
||||
const GLVolume* v = m_volumes.volumes[i];
|
||||
assert(v->mesh_raycaster != nullptr);
|
||||
@@ -2707,6 +2658,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
if (curr_gizmo != nullptr)
|
||||
curr_gizmo->unregister_raycasters_for_picking();
|
||||
m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Gizmo);
|
||||
m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::FallbackGizmo);
|
||||
if (curr_gizmo != nullptr && !m_selection.is_empty())
|
||||
curr_gizmo->register_raycasters_for_picking();
|
||||
|
||||
@@ -2714,6 +2666,13 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GLCanvas3D::load_gcode_shells()
|
||||
{
|
||||
m_gcode_viewer.load_shells(*this->fff_print());
|
||||
m_gcode_viewer.update_shells_color_by_extruder(m_config);
|
||||
m_gcode_viewer.set_force_shells_visible(true);
|
||||
}
|
||||
|
||||
void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
m_gcode_viewer.load(gcode_result, *this->fff_print());
|
||||
@@ -2721,7 +2680,6 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co
|
||||
if (wxGetApp().is_editor()) {
|
||||
//Y5
|
||||
isToolpathOutside = false;
|
||||
m_gcode_viewer.update_shells_color_by_extruder(m_config);
|
||||
_set_warning_notification_if_needed(EWarning::ToolpathOutside);
|
||||
_set_warning_notification_if_needed(EWarning::GCodeConflict);
|
||||
}
|
||||
@@ -2769,6 +2727,7 @@ void GLCanvas3D::load_preview(const std::vector<std::string>& str_tool_colors, c
|
||||
for (const PrintObject* object : print->objects())
|
||||
_load_print_object_toolpaths(*object, build_volume, str_tool_colors, color_print_values);
|
||||
|
||||
m_gcode_viewer.set_force_shells_visible(false);
|
||||
_set_warning_notification_if_needed(EWarning::ToolpathOutside);
|
||||
}
|
||||
|
||||
@@ -2883,7 +2842,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
||||
|
||||
#ifdef SHOW_IMGUI_DEMO_WINDOW
|
||||
static int cur = 0;
|
||||
if (wxString("demo")[cur] == evt.GetUnicodeKey()) ++cur; else cur = 0;
|
||||
if (get_logging_level() >= 3 && wxString("demo")[cur] == evt.GetUnicodeKey()) ++cur; else cur = 0;
|
||||
if (cur == 4) { show_imgui_demo_window = !show_imgui_demo_window; cur = 0;}
|
||||
#endif // SHOW_IMGUI_DEMO_WINDOW
|
||||
|
||||
@@ -2900,8 +2859,15 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
||||
if (keyCode == WXK_ESCAPE && (_deactivate_undo_redo_toolbar_items() || _deactivate_search_toolbar_item() || _deactivate_arrange_menu()))
|
||||
return;
|
||||
|
||||
if (m_gizmos.on_char(evt))
|
||||
if (m_gizmos.on_char(evt)) {
|
||||
if (m_gizmos.get_current_type() == GLGizmosManager::EType::Scale &&
|
||||
m_gizmos.get_current()->get_state() == GLGizmoBase::EState::On) {
|
||||
// Update selection from object list to check selection of the cut objects
|
||||
// It's not allowed to scale separate ct parts
|
||||
wxGetApp().obj_list()->selection_changed();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((evt.GetModifiers() & ctrlMask) != 0) {
|
||||
// CTRL is pressed
|
||||
@@ -3198,7 +3164,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
||||
else {
|
||||
if (!m_gizmos.on_key(evt)) {
|
||||
if (evt.GetEventType() == wxEVT_KEY_UP) {
|
||||
if (evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_SPACE) {
|
||||
if (get_logging_level() >= 3 && evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_SPACE) {
|
||||
wxGetApp().plater()->toggle_render_statistic_dialog();
|
||||
m_dirty = true;
|
||||
}
|
||||
@@ -3620,6 +3586,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
else if (evt.LeftUp() &&
|
||||
m_gizmos.get_current_type() == GLGizmosManager::EType::Scale &&
|
||||
m_gizmos.get_current()->get_state() == GLGizmoBase::EState::On) {
|
||||
// Update selection from object list to check selection of the cut objects
|
||||
// It's not allowed to scale separate ct parts
|
||||
wxGetApp().obj_list()->selection_changed();
|
||||
}
|
||||
|
||||
@@ -4091,7 +4059,7 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
model_object->invalidate_bounding_box();
|
||||
}
|
||||
}
|
||||
else if (v->is_wipe_tower)
|
||||
else if (m_selection.is_wipe_tower() && v->is_wipe_tower)
|
||||
// Move a wipe tower proxy.
|
||||
wipe_tower_origin = v->get_volume_offset();
|
||||
}
|
||||
@@ -4844,104 +4812,9 @@ bool GLCanvas3D::_render_search_list(float pos_x)
|
||||
|
||||
bool GLCanvas3D::_render_arrange_menu(float pos_x)
|
||||
{
|
||||
ImGuiWrapper *imgui = wxGetApp().imgui();
|
||||
m_arrange_settings_dialog.render(pos_x, m_main_toolbar.get_height());
|
||||
|
||||
imgui->set_next_window_pos(pos_x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f);
|
||||
|
||||
imgui->begin(_L("Arrange options"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
ArrangeSettings settings = get_arrange_settings();
|
||||
ArrangeSettings &settings_out = get_arrange_settings_ref(this);
|
||||
|
||||
auto &appcfg = wxGetApp().app_config;
|
||||
PrinterTechnology ptech = current_printer_technology();
|
||||
|
||||
bool settings_changed = false;
|
||||
float dist_min = 0.f;
|
||||
float dist_bed_min = 0.f;
|
||||
std::string dist_key = "min_object_distance";
|
||||
std::string dist_bed_key = "min_bed_distance";
|
||||
std::string rot_key = "enable_rotation";
|
||||
std::string align_key = "alignment";
|
||||
std::string postfix;
|
||||
|
||||
if (ptech == ptSLA) {
|
||||
postfix = "_sla";
|
||||
} else if (ptech == ptFFF) {
|
||||
auto co_opt = m_config->option<ConfigOptionBool>("complete_objects");
|
||||
if (co_opt && co_opt->value) {
|
||||
dist_min = float(min_object_distance(*m_config));
|
||||
postfix = "_fff_seq_print";
|
||||
} else {
|
||||
dist_min = 0.f;
|
||||
postfix = "_fff";
|
||||
}
|
||||
}
|
||||
|
||||
dist_key += postfix;
|
||||
dist_bed_key += postfix;
|
||||
rot_key += postfix;
|
||||
align_key += postfix;
|
||||
|
||||
imgui->text(GUI::format_wxstr(_L("Press %1%left mouse button to enter the exact value"), shortkey_ctrl_prefix()));
|
||||
|
||||
if (imgui->slider_float(_L("Spacing"), &settings.distance, dist_min, 100.0f, "%5.2f") || dist_min > settings.distance) {
|
||||
settings.distance = std::max(dist_min, settings.distance);
|
||||
settings_out.distance = settings.distance;
|
||||
appcfg->set("arrange", dist_key.c_str(), float_to_string_decimal_point(settings_out.distance));
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if (imgui->slider_float(_L("Spacing from bed"), &settings.distance_from_bed, dist_bed_min, 100.0f, "%5.2f") || dist_bed_min > settings.distance_from_bed) {
|
||||
settings.distance_from_bed = std::max(dist_bed_min, settings.distance_from_bed);
|
||||
settings_out.distance_from_bed = settings.distance_from_bed;
|
||||
appcfg->set("arrange", dist_bed_key.c_str(), float_to_string_decimal_point(settings_out.distance_from_bed));
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if (imgui->checkbox(_L("Enable rotations (slow)"), settings.enable_rotation)) {
|
||||
settings_out.enable_rotation = settings.enable_rotation;
|
||||
appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation? "1" : "0");
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
Points bed = m_config ? get_bed_shape(*m_config) : Points{};
|
||||
|
||||
if (arrangement::is_box(bed) && settings.alignment >= 0 &&
|
||||
imgui->combo(_L("Alignment"), {_u8L("Center"), _u8L("Rear left"), _u8L("Front left"), _u8L("Front right"), _u8L("Rear right"), _u8L("Random") }, settings.alignment)) {
|
||||
settings_out.alignment = settings.alignment;
|
||||
appcfg->set("arrange", align_key.c_str(), std::to_string(settings_out.alignment));
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (imgui->button(_L("Reset"))) {
|
||||
auto alignment = settings_out.alignment;
|
||||
settings_out = ArrangeSettings{};
|
||||
settings_out.distance = std::max(dist_min, settings_out.distance);
|
||||
|
||||
// Default alignment for XL printers set explicitly:
|
||||
if (is_arrange_alignment_enabled())
|
||||
settings_out.alignment = static_cast<int>(arrangement::Pivots::BottomLeft);
|
||||
else
|
||||
settings_out.alignment = alignment;
|
||||
|
||||
appcfg->set("arrange", dist_key.c_str(), float_to_string_decimal_point(settings_out.distance));
|
||||
appcfg->set("arrange", dist_bed_key.c_str(), float_to_string_decimal_point(settings_out.distance_from_bed));
|
||||
appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation? "1" : "0");
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (imgui->button(_L("Arrange"))) {
|
||||
wxGetApp().plater()->arrange();
|
||||
}
|
||||
|
||||
imgui->end();
|
||||
|
||||
return settings_changed;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT 0
|
||||
@@ -5771,6 +5644,7 @@ void GLCanvas3D::_picking_pass()
|
||||
break;
|
||||
}
|
||||
case SceneRaycaster::EType::Gizmo:
|
||||
case SceneRaycaster::EType::FallbackGizmo:
|
||||
{
|
||||
const Size& cnv_size = get_canvas_size();
|
||||
const bool inside = 0 <= m_mouse.position.x() && m_mouse.position.x() < cnv_size.get_width() &&
|
||||
@@ -5803,6 +5677,7 @@ void GLCanvas3D::_picking_pass()
|
||||
{
|
||||
case SceneRaycaster::EType::Bed: { object_type = "Bed"; break; }
|
||||
case SceneRaycaster::EType::Gizmo: { object_type = "Gizmo element"; break; }
|
||||
case SceneRaycaster::EType::FallbackGizmo: { object_type = "Gizmo2 element"; break; }
|
||||
case SceneRaycaster::EType::Volume:
|
||||
{
|
||||
if (m_volumes.volumes[hit.raycaster_id]->is_wipe_tower)
|
||||
@@ -5859,6 +5734,8 @@ void GLCanvas3D::_picking_pass()
|
||||
add_strings_row_to_table("Volumes", ImGuiWrapper::COL_BLUE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.gizmos_count(), (int)m_scene_raycaster.active_gizmos_count());
|
||||
add_strings_row_to_table("Gizmo elements", ImGuiWrapper::COL_BLUE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.fallback_gizmos_count(), (int)m_scene_raycaster.active_fallback_gizmos_count());
|
||||
add_strings_row_to_table("Gizmo2 elements", ImGuiWrapper::COL_BLUE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
@@ -5877,6 +5754,20 @@ void GLCanvas3D::_picking_pass()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* gizmo2_raycasters = m_scene_raycaster.get_raycasters(SceneRaycaster::EType::FallbackGizmo);
|
||||
if (gizmo2_raycasters != nullptr && !gizmo2_raycasters->empty()) {
|
||||
ImGui::Separator();
|
||||
imgui.text("Gizmo2 raycasters IDs:");
|
||||
if (ImGui::BeginTable("Gizmo2Raycasters", 3)) {
|
||||
for (size_t i = 0; i < gizmo2_raycasters->size(); ++i) {
|
||||
add_strings_row_to_table(std::to_string(i), ImGuiWrapper::COL_BLUE_LIGHT,
|
||||
std::to_string(SceneRaycaster::decode_id(SceneRaycaster::EType::FallbackGizmo, (*gizmo2_raycasters)[i]->get_id())), ImGui::GetStyleColorVec4(ImGuiCol_Text),
|
||||
to_string(Geometry::Transformation((*gizmo2_raycasters)[i]->get_transform()).get_offset()), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
imgui.end();
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
}
|
||||
@@ -6190,7 +6081,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type)
|
||||
}
|
||||
}
|
||||
if (m_requires_check_outside_state) {
|
||||
check_volumes_outside_state(build_volume, nullptr);
|
||||
check_volumes_outside_state(m_volumes, nullptr);
|
||||
m_requires_check_outside_state = false;
|
||||
}
|
||||
}
|
||||
@@ -7787,15 +7678,20 @@ const SLAPrint* GLCanvas3D::sla_print() const
|
||||
return (m_process == nullptr) ? nullptr : m_process->sla_print();
|
||||
}
|
||||
|
||||
void GLCanvas3D::WipeTowerInfo::apply_wipe_tower() const
|
||||
void GLCanvas3D::WipeTowerInfo::apply_wipe_tower(Vec2d pos, double rot)
|
||||
{
|
||||
DynamicPrintConfig cfg;
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = m_pos(X);
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = m_pos(Y);
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_rotation_angle", true)->value = (180./M_PI) * m_rotation;
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = pos.x();
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = pos.y();
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_rotation_angle", true)->value = (180./M_PI) * rot;
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg);
|
||||
}
|
||||
|
||||
void GLCanvas3D::WipeTowerInfo::apply_wipe_tower() const
|
||||
{
|
||||
apply_wipe_tower(m_pos, m_rotation);
|
||||
}
|
||||
|
||||
void GLCanvas3D::RenderTimer::Notify()
|
||||
{
|
||||
wxPostEvent((wxEvtHandler*)GetOwner(), RenderTimerEvent( EVT_GLCANVAS_RENDER_TIMER, *this));
|
||||
|
||||
Reference in New Issue
Block a user