Merge branch 'master' of https://github.com/Prusa-Development/PrusaSlicerPrivate
This commit is contained in:
commit
cc9aba8474
14 changed files with 302 additions and 135 deletions
|
@ -3,11 +3,10 @@
|
|||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="expand">
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="8" x2="8" y2="4"/></g>
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="4" x2="12" y2="8"/></g>
|
||||
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="12" x2="8" y2="8"/></g>
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="8" x2="12" y2="12"/></g>
|
||||
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="4" x2="8" y2="8"/></g>
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="8" x2="12" y2="4"/></g>
|
||||
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="8" x2="8" y2="12"/></g>
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12" x2="12" y2="8"/></g>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 919 B After Width: | Height: | Size: 915 B |
|
@ -3,10 +3,11 @@
|
|||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="expand">
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="4" x2="8" y2="8"/></g>
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="8" x2="12" y2="4"/></g>
|
||||
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="8" x2="8" y2="12"/></g>
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12" x2="12" y2="8"/></g>
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="8" x2="8" y2="4"/></g>
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="4" x2="12" y2="8"/></g>
|
||||
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="12" x2="8" y2="8"/></g>
|
||||
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="8" x2="12" y2="12"/></g>
|
||||
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
Before Width: | Height: | Size: 915 B After Width: | Height: | Size: 919 B |
|
@ -1154,7 +1154,7 @@ indexed_triangle_set its_make_frustum_dowel(double radius, double h, int sectorC
|
|||
else
|
||||
for (int j = 0; j < sectorCount; ++j) {
|
||||
// from 0 to 2pi
|
||||
double sectorAngle = sectorStep * j;
|
||||
double sectorAngle = sectorStep * j + 0.25 * M_PI;
|
||||
vertices.emplace_back(Vec3d(xy * std::cos(sectorAngle), xy * std::sin(sectorAngle), z).cast<float>());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1755,7 +1755,20 @@ std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
|
|||
|
||||
void GLCanvas3D::mirror_selection(Axis axis)
|
||||
{
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
TransformationType transformation_type;
|
||||
if (wxGetApp().obj_manipul()->is_local_coordinates())
|
||||
transformation_type.set_local();
|
||||
else if (wxGetApp().obj_manipul()->is_instance_coordinates())
|
||||
transformation_type.set_instance();
|
||||
|
||||
transformation_type.set_relative();
|
||||
|
||||
m_selection.setup_cache();
|
||||
m_selection.mirror(axis, transformation_type);
|
||||
#else
|
||||
m_selection.mirror(axis);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
do_mirror(L("Mirror Object"));
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
}
|
||||
|
@ -3646,7 +3659,13 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
|||
for (const GLVolume* v : m_volumes.volumes) {
|
||||
if (v->is_wipe_tower) {
|
||||
const Vec3d offset = v->get_volume_offset();
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
Vec3d rot_unit_x = v->get_volume_transformation().get_matrix().linear() * Vec3d::UnitX();
|
||||
double z_rot = std::atan2(rot_unit_x.y(), rot_unit_x.x());
|
||||
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), z_rot)));
|
||||
#else
|
||||
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), v->get_volume_rotation().z())));
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
const int object_idx = v->object_idx();
|
||||
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
|
||||
|
@ -5096,9 +5115,17 @@ void GLCanvas3D::_refresh_if_shown_on_screen()
|
|||
const Size& cnv_size = get_canvas_size();
|
||||
_resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
|
||||
|
||||
// When the application starts the following call to render() triggers the opengl initialization.
|
||||
// We need to ask for an extra call to reload_scene() to force the generation of the model for wipe tower
|
||||
// for printers using it, which is skipped by all the previous calls to reload_scene() because m_initialized == false
|
||||
const bool requires_reload_scene = !m_initialized;
|
||||
|
||||
// Because of performance problems on macOS, where PaintEvents are not delivered
|
||||
// frequently enough, we call render() here directly when we can.
|
||||
render();
|
||||
assert(m_initialized);
|
||||
if (requires_reload_scene)
|
||||
reload_scene(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2216,6 +2216,17 @@ bool GUI_App::load_language(wxString language, bool initial)
|
|||
// Override language at the active wxTranslations class (which is stored in the active m_wxLocale)
|
||||
// to load possibly different dictionary, for example, load Czech dictionary for Slovak language.
|
||||
wxTranslations::Get()->SetLanguage(language_dict);
|
||||
{
|
||||
// UKR Localization specific workaround till the wxWidgets doesn't fixed:
|
||||
// From wxWidgets 3.1.6 calls setlocation(0, wxInfoLanguage->LocaleTag), see (https://github.com/prusa3d/wxWidgets/commit/deef116a09748796711d1e3509965ee208dcdf0b#diff-7de25e9a71c4dce61bbf76492c589623d5b93fd1bb105ceaf0662075d15f4472),
|
||||
// where LocaleTag is a Tag of locale in BCP 47 - like notation.
|
||||
// For Ukrainian Language LocaleTag == "uk".
|
||||
// But setlocale(0, "uk") returns "English_United Kingdom.1252" instead of "uk",
|
||||
// and, as a result, locales are set to English_United Kingdom
|
||||
|
||||
if (language_info->CanonicalName == "uk")
|
||||
setlocale(0, language_info->GetCanonicalWithRegion().data());
|
||||
}
|
||||
m_wxLocale->AddCatalog(SLIC3R_APP_KEY);
|
||||
m_imgui->set_language(into_u8(language_info->CanonicalName));
|
||||
//FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only.
|
||||
|
|
|
@ -2825,8 +2825,12 @@ void ObjectList::part_selection_changed()
|
|||
panel.Freeze();
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const ManipulationEditor* const editor = wxGetApp().obj_manipul()->get_focused_editor();
|
||||
const std::string opt_key = (editor != nullptr) ? editor->get_full_opt_name() : "";
|
||||
std::string opt_key;
|
||||
if (m_selected_object_id >= 0) {
|
||||
const ManipulationEditor* const editor = wxGetApp().obj_manipul()->get_focused_editor();
|
||||
if (editor != nullptr)
|
||||
opt_key = editor->get_full_opt_name();
|
||||
}
|
||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, !opt_key.empty());
|
||||
#else
|
||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
|
||||
|
|
|
@ -125,8 +125,10 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
|
||||
// Load bitmaps to be used for the mirroring buttons:
|
||||
m_mirror_bitmap_on = ScalableBitmap(parent, "mirroring_on");
|
||||
#if !ENABLE_WORLD_COORDINATE
|
||||
m_mirror_bitmap_off = ScalableBitmap(parent, "mirroring_off");
|
||||
m_mirror_bitmap_hidden = ScalableBitmap(parent, "mirroring_transparent");
|
||||
#endif // !ENABLE_WORLD_COORDINATE
|
||||
|
||||
const int border = wxOSX ? 0 : 4;
|
||||
const int em = wxGetApp().em_unit();
|
||||
|
@ -265,28 +267,44 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
|
||||
// We will add a button to toggle mirroring to each axis:
|
||||
auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW);
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
btn->SetToolTip(_L("Mirror along") + wxString::Format(_L(" %c "), (int)label) + _L("axis"));
|
||||
|
||||
m_mirror_buttons[axis_idx] = btn;
|
||||
#else
|
||||
btn->SetToolTip(wxString::Format(_L("Toggle %c axis mirroring"), (int)label));
|
||||
btn->SetBitmapDisabled_(m_mirror_bitmap_hidden);
|
||||
|
||||
m_mirror_buttons[axis_idx].first = btn;
|
||||
m_mirror_buttons[axis_idx].second = mbShown;
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
sizer->AddStretchSpacer(2);
|
||||
sizer->Add(btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
btn->Bind(wxEVT_BUTTON, [this, axis_idx](wxCommandEvent&) {
|
||||
#if !ENABLE_WORLD_COORDINATE
|
||||
Axis axis = (Axis)(axis_idx + X);
|
||||
if (m_mirror_buttons[axis_idx].second == mbHidden)
|
||||
return;
|
||||
return;
|
||||
#endif // !ENABLE_WORLD_COORDINATE
|
||||
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||
Selection& selection = canvas->get_selection();
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (selection.is_single_volume_or_modifier()) {
|
||||
TransformationType transformation_type;
|
||||
if (is_local_coordinates())
|
||||
transformation_type.set_local();
|
||||
else if (is_instance_coordinates())
|
||||
transformation_type.set_instance();
|
||||
|
||||
transformation_type.set_relative();
|
||||
|
||||
selection.setup_cache();
|
||||
selection.mirror((Axis)axis_idx, transformation_type);
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
GLVolume* volume = const_cast<GLVolume*>(selection.get_first_volume());
|
||||
volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis));
|
||||
}
|
||||
|
@ -302,6 +320,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
// Update mirroring at the GLVolumes.
|
||||
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
|
||||
selection.synchronize_unselected_volumes();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
// Copy mirroring values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
|
||||
canvas->do_mirror(L("Set Mirror"));
|
||||
UpdateAndShow(true);
|
||||
|
@ -310,7 +329,12 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
editors_grid_sizer->Add(sizer, 0, wxALIGN_CENTER_HORIZONTAL);
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
m_mirror_warning_bitmap = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap);
|
||||
editors_grid_sizer->Add(m_mirror_warning_bitmap, 0, wxALIGN_CENTER_VERTICAL);
|
||||
#else
|
||||
editors_grid_sizer->AddStretchSpacer(1);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
editors_grid_sizer->AddStretchSpacer(1);
|
||||
|
||||
// add EditBoxes
|
||||
|
@ -541,15 +565,15 @@ void ObjectManipulation::Show(const bool show)
|
|||
bool show_world_local_combo = wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier());
|
||||
if (selection.is_single_volume_or_modifier() && m_word_local_combo->GetCount() < 3) {
|
||||
#ifdef __linux__
|
||||
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Instance), 1);
|
||||
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Local), 2);
|
||||
#else
|
||||
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Instance), wxNullBitmap, 1);
|
||||
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Local), wxNullBitmap, 2);
|
||||
#endif // __linux__
|
||||
m_word_local_combo->Select((int)ECoordinatesType::World);
|
||||
this->set_coordinates_type(m_word_local_combo->GetString(m_word_local_combo->GetSelection()));
|
||||
}
|
||||
else if (selection.is_single_full_instance() && m_word_local_combo->GetCount() > 2) {
|
||||
m_word_local_combo->Delete(1);
|
||||
m_word_local_combo->Delete(2);
|
||||
m_word_local_combo->Select((int)ECoordinatesType::World);
|
||||
this->set_coordinates_type(m_word_local_combo->GetString(m_word_local_combo->GetSelection()));
|
||||
}
|
||||
|
@ -660,7 +684,7 @@ void ObjectManipulation::update_ui_from_settings()
|
|||
|
||||
void ObjectManipulation::update_settings_value(const Selection& selection)
|
||||
{
|
||||
m_new_move_label_string = L("Position");
|
||||
m_new_move_label_string = L("Position");
|
||||
m_new_rotate_label_string = L("Rotation");
|
||||
m_new_scale_label_string = L("Scale factors");
|
||||
|
||||
|
@ -688,13 +712,15 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
#if ENABLE_WORLD_COORDINATE
|
||||
if (is_world_coordinates()) {
|
||||
m_new_position = volume->get_instance_offset();
|
||||
m_new_scale_label_string = L("Scale");
|
||||
m_new_scale = Vec3d(100.0, 100.0, 100.0);
|
||||
#else
|
||||
if (m_world_coordinates) {
|
||||
m_new_scale = m_new_size.cwiseQuotient(selection.get_unscaled_instance_bounding_box().size()) * 100.0;
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_rotation = Vec3d::Zero();
|
||||
m_new_size = selection.get_scaled_instance_bounding_box().size();
|
||||
m_new_scale = m_new_size.cwiseQuotient(selection.get_unscaled_instance_bounding_box().size()) * 100.0;
|
||||
}
|
||||
else {
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
|
@ -702,12 +728,13 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_position = Vec3d::Zero();
|
||||
m_new_rotation = Vec3d::Zero();
|
||||
m_new_scale = Vec3d(100.0, 100.0, 100.0);
|
||||
#else
|
||||
m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
m_new_scale = volume->get_instance_scaling_factor() * 100.0;
|
||||
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size());
|
||||
m_new_scale = volume->get_instance_scaling_factor() * 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
m_new_enabled = true;
|
||||
}
|
||||
|
@ -718,7 +745,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
m_new_scale = Vec3d(100.0, 100.0, 100.0);
|
||||
m_new_size = box.size();
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_scale_label_string = L("Scale");
|
||||
m_new_scale_label_string = L("Scale");
|
||||
m_new_enabled = true;
|
||||
}
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
|
@ -736,9 +763,10 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
|
||||
m_new_position = offset;
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_scale_label_string = L("Scale");
|
||||
m_new_scale = Vec3d(100.0, 100.0, 100.0);
|
||||
m_new_rotation = Vec3d::Zero();
|
||||
m_new_size = volume->transformed_convex_hull_bounding_box(trafo.get_matrix()).size();
|
||||
m_new_scale = m_new_size.cwiseQuotient(volume->transformed_convex_hull_bounding_box(volume->get_instance_transformation().get_matrix() * volume->get_volume_transformation().get_matrix_no_scaling_factor()).size()) * 100.0;
|
||||
}
|
||||
else if (is_local_coordinates()) {
|
||||
m_new_move_label_string = L("Translate");
|
||||
|
@ -750,12 +778,13 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
}
|
||||
else {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
m_new_position = volume->get_volume_offset();
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_rotation = Vec3d::Zero();
|
||||
m_new_position = volume->get_volume_offset();
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_rotation = Vec3d::Zero();
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
m_new_scale_label_string = L("Scale");
|
||||
m_new_size = volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix()).size();
|
||||
m_new_scale = m_new_size.cwiseQuotient(volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix_no_scaling_factor()).size()) * 100.0;
|
||||
m_new_scale = Vec3d(100.0, 100.0, 100.0);
|
||||
}
|
||||
#else
|
||||
m_new_scale = volume->get_volume_scaling_factor() * 100.0;
|
||||
|
@ -765,17 +794,17 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
}
|
||||
else if (obj_list->is_connectors_item_selected() || obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) {
|
||||
reset_settings_value();
|
||||
m_new_move_label_string = L("Translate");
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_scale_label_string = L("Scale");
|
||||
m_new_move_label_string = L("Translate");
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_scale_label_string = L("Scale");
|
||||
m_new_size = selection.get_bounding_box().size();
|
||||
m_new_enabled = true;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
// No selection, reset the cache.
|
||||
// assert(selection.is_empty());
|
||||
reset_settings_value();
|
||||
}
|
||||
reset_settings_value();
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectManipulation::update_if_dirty()
|
||||
|
@ -882,6 +911,7 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||
bool show_drop_to_bed = false;
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
bool show_skew = false;
|
||||
bool show_mirror_warning = false;
|
||||
|
||||
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
|
||||
const double min_z = selection.is_single_full_instance() ? selection.get_scaled_instance_bounding_box().min.z() :
|
||||
|
@ -891,7 +921,6 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||
const GLVolume* volume = selection.get_first_volume();
|
||||
Transform3d rotation = Transform3d::Identity();
|
||||
Transform3d scale = Transform3d::Identity();
|
||||
Geometry::Transformation skew;
|
||||
#else
|
||||
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
||||
const GLVolume* volume = selection.get_first_volume();
|
||||
|
@ -907,11 +936,9 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||
scale = trafo.get_scaling_factor_matrix();
|
||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
||||
for (unsigned int id : idxs) {
|
||||
const Geometry::Transformation world_trafo(selection.get_volume(id)->world_matrix());
|
||||
if (world_trafo.has_skew()) {
|
||||
skew = world_trafo;
|
||||
break;
|
||||
}
|
||||
const Geometry::Transformation world_trafo(selection.get_volume(id)->world_matrix());
|
||||
show_skew |= world_trafo.has_skew();
|
||||
show_mirror_warning |= world_trafo.get_matrix().matrix().determinant() < 0.0;
|
||||
}
|
||||
#else
|
||||
rotation = volume->get_instance_rotation();
|
||||
|
@ -925,8 +952,8 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||
rotation = trafo.get_rotation_matrix();
|
||||
scale = trafo.get_scaling_factor_matrix();
|
||||
const Geometry::Transformation world_trafo(volume->world_matrix());
|
||||
if (world_trafo.has_skew())
|
||||
skew = world_trafo;
|
||||
show_skew |= world_trafo.has_skew();
|
||||
show_mirror_warning |= world_trafo.get_matrix().matrix().determinant() < 0.0;
|
||||
#else
|
||||
rotation = volume->get_volume_rotation();
|
||||
scale = volume->get_volume_scaling_factor();
|
||||
|
@ -936,7 +963,6 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||
#if ENABLE_WORLD_COORDINATE
|
||||
show_rotation = !rotation.isApprox(Transform3d::Identity());
|
||||
show_scale = !scale.isApprox(Transform3d::Identity());
|
||||
show_skew = skew.has_skew();
|
||||
#else
|
||||
show_rotation = !rotation.isApprox(Vec3d::Zero());
|
||||
show_scale = !scale.isApprox(Vec3d::Ones());
|
||||
|
@ -945,7 +971,7 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed, show_skew] {
|
||||
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed, show_skew, show_mirror_warning] {
|
||||
#else
|
||||
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed] {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
@ -959,6 +985,9 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||
#if ENABLE_WORLD_COORDINATE
|
||||
m_reset_skew_button->Show(show_skew);
|
||||
m_skew_label->Show(show_skew);
|
||||
m_mirror_warning_bitmap->SetBitmap(show_mirror_warning ? m_manifold_warning_bmp.bmp() : wxNullBitmap);
|
||||
m_mirror_warning_bitmap->SetMinSize(show_mirror_warning ? m_manifold_warning_bmp.GetSize() : wxSize(0, 0));
|
||||
m_mirror_warning_bitmap->SetToolTip(show_mirror_warning ? _L("Left handed") : "");
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
// Because of CallAfter we need to layout sidebar after Show/hide of reset buttons one more time
|
||||
|
@ -977,16 +1006,14 @@ void ObjectManipulation::update_mirror_buttons_visibility()
|
|||
{
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||
Selection& selection = canvas->get_selection();
|
||||
std::array<MirrorButtonState, 3> new_states = {mbHidden, mbHidden, mbHidden};
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (is_local_coordinates()) {
|
||||
#else
|
||||
if (!m_world_coordinates) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
|
||||
#else
|
||||
std::array<MirrorButtonState, 3> new_states = { mbHidden, mbHidden, mbHidden };
|
||||
|
||||
if (!m_world_coordinates) {
|
||||
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
const GLVolume* volume = selection.get_first_volume();
|
||||
|
@ -997,10 +1024,13 @@ void ObjectManipulation::update_mirror_buttons_visibility()
|
|||
else
|
||||
mirror = volume->get_volume_mirror();
|
||||
|
||||
#if !ENABLE_WORLD_COORDINATE
|
||||
for (unsigned char i=0; i<3; ++i)
|
||||
new_states[i] = (mirror[i] < 0. ? mbActive : mbShown);
|
||||
#endif // !ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
}
|
||||
#if !ENABLE_WORLD_COORDINATE
|
||||
else {
|
||||
// the mirroring buttons should be hidden in world coordinates,
|
||||
// unless we make it actually mirror in world coords.
|
||||
|
@ -1022,6 +1052,7 @@ void ObjectManipulation::update_mirror_buttons_visibility()
|
|||
}
|
||||
}
|
||||
});
|
||||
#endif // !ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
|
||||
|
@ -1059,8 +1090,8 @@ wxString ObjectManipulation::coordinate_type_str(ECoordinatesType type)
|
|||
switch (type)
|
||||
{
|
||||
case ECoordinatesType::World: { return _L("World coordinates"); }
|
||||
case ECoordinatesType::Instance: { return _L("Instance coordinates"); }
|
||||
case ECoordinatesType::Local: { return _L("Local coordinates"); }
|
||||
case ECoordinatesType::Instance: { return _L("Object coordinates"); }
|
||||
case ECoordinatesType::Local: { return _L("Part coordinates"); }
|
||||
default: { assert(false); return _L("Unknown"); }
|
||||
}
|
||||
}
|
||||
|
@ -1162,13 +1193,24 @@ void ObjectManipulation::change_scale_value(int axis, double value)
|
|||
return;
|
||||
|
||||
Vec3d scale = m_cache.scale;
|
||||
scale(axis) = value;
|
||||
scale(axis) = value;
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
Vec3d ref_scale = m_cache.scale;
|
||||
if (selection.is_single_full_instance()) {
|
||||
scale = scale.cwiseQuotient(ref_scale);
|
||||
ref_scale = Vec3d::Ones();
|
||||
}
|
||||
|
||||
this->do_scale(axis, scale.cwiseQuotient(ref_scale));
|
||||
#else
|
||||
this->do_scale(axis, 0.01 * scale);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
m_cache.scale = scale;
|
||||
m_cache.scale_rounded(axis) = DBL_MAX;
|
||||
this->UpdateAndShow(true);
|
||||
m_cache.scale_rounded(axis) = DBL_MAX;
|
||||
this->UpdateAndShow(true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1195,9 +1237,12 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
|||
Vec3d ref_size = m_cache.size;
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (selection.is_single_volume_or_modifier()) {
|
||||
if (is_local_coordinates())
|
||||
ref_size = selection.get_first_volume()->bounding_box().size();
|
||||
size = size.cwiseQuotient(ref_size);
|
||||
ref_size = Vec3d::Ones();
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
const GLVolume* v = selection.get_first_volume();
|
||||
const Vec3d local_size = size.cwiseQuotient(v->get_instance_scaling_factor());
|
||||
const Vec3d local_ref_size = v->bounding_box().size().cwiseProduct(v->get_volume_scaling_factor());
|
||||
|
@ -1205,15 +1250,20 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
|||
|
||||
size = local_change.cwiseProduct(v->get_volume_scaling_factor());
|
||||
ref_size = Vec3d::Ones();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
else if (selection.is_single_full_instance())
|
||||
else if (selection.is_single_full_instance()) {
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
ref_size = is_world_coordinates() ?
|
||||
if (is_world_coordinates())
|
||||
ref_size = selection.get_unscaled_instance_bounding_box().size();
|
||||
size = size.cwiseQuotient(ref_size);
|
||||
ref_size = Vec3d::Ones();
|
||||
#else
|
||||
ref_size = m_world_coordinates ?
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
selection.get_unscaled_instance_bounding_box().size() :
|
||||
wxGetApp().model().objects[selection.get_first_volume()->object_idx()]->raw_mesh_bounding_box().size();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
this->do_size(axis, size.cwiseQuotient(ref_size));
|
||||
|
@ -1222,8 +1272,8 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
|||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
m_cache.size = size;
|
||||
m_cache.size_rounded(axis) = DBL_MAX;
|
||||
this->UpdateAndShow(true);
|
||||
m_cache.size_rounded(axis) = DBL_MAX;
|
||||
this->UpdateAndShow(true);
|
||||
}
|
||||
|
||||
void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
|
||||
|
@ -1240,7 +1290,8 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
|
|||
else if (is_instance_coordinates())
|
||||
transformation_type.set_instance();
|
||||
|
||||
if (!selection.is_single_full_instance() && !selection.is_single_volume_or_modifier())
|
||||
if (!(selection.is_single_volume_or_modifier() && is_local_coordinates()) &&
|
||||
!(selection.is_single_full_instance() && is_instance_coordinates()))
|
||||
transformation_type.set_relative();
|
||||
|
||||
const Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
|
||||
|
@ -1425,15 +1476,23 @@ void ObjectManipulation::sys_color_changed()
|
|||
editor->sys_color_changed(this);
|
||||
|
||||
m_mirror_bitmap_on.sys_color_changed();
|
||||
#if !ENABLE_WORLD_COORDINATE
|
||||
m_mirror_bitmap_off.sys_color_changed();
|
||||
m_mirror_bitmap_hidden.sys_color_changed();
|
||||
#endif // !ENABLE_WORLD_COORDINATE
|
||||
m_reset_scale_button->sys_color_changed();
|
||||
m_reset_rotation_button->sys_color_changed();
|
||||
m_drop_to_bed_button->sys_color_changed();
|
||||
m_lock_bnt->sys_color_changed();
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
for (int id = 0; id < 3; ++id) {
|
||||
m_mirror_buttons[id]->sys_color_changed();
|
||||
}
|
||||
#else
|
||||
for (int id = 0; id < 3; ++id)
|
||||
m_mirror_buttons[id].first->sys_color_changed();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
|
|
|
@ -132,6 +132,9 @@ private:
|
|||
|
||||
wxCheckBox* m_check_inch {nullptr};
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
std::array<ScalableButton*, 3> m_mirror_buttons;
|
||||
#else
|
||||
// Mirroring buttons and their current state
|
||||
enum MirrorButtonState {
|
||||
mbHidden,
|
||||
|
@ -139,18 +142,21 @@ private:
|
|||
mbActive
|
||||
};
|
||||
std::array<std::pair<ScalableButton*, MirrorButtonState>, 3> m_mirror_buttons;
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
// Bitmaps for the mirroring buttons.
|
||||
ScalableBitmap m_mirror_bitmap_on;
|
||||
#if !ENABLE_WORLD_COORDINATE
|
||||
ScalableBitmap m_mirror_bitmap_off;
|
||||
ScalableBitmap m_mirror_bitmap_hidden;
|
||||
#endif // !ENABLE_WORLD_COORDINATE
|
||||
|
||||
// Needs to be updated from OnIdle?
|
||||
bool m_dirty = false;
|
||||
// Cached labels for the delayed update, not localized!
|
||||
std::string m_new_move_label_string;
|
||||
std::string m_new_rotate_label_string;
|
||||
std::string m_new_scale_label_string;
|
||||
std::string m_new_rotate_label_string;
|
||||
std::string m_new_scale_label_string;
|
||||
Vec3d m_new_position;
|
||||
Vec3d m_new_rotation;
|
||||
Vec3d m_new_scale;
|
||||
|
@ -167,7 +173,10 @@ private:
|
|||
choice_ctrl* m_word_local_combo { nullptr };
|
||||
|
||||
ScalableBitmap m_manifold_warning_bmp;
|
||||
wxStaticBitmap* m_fix_throught_netfab_bitmap;
|
||||
wxStaticBitmap* m_fix_throught_netfab_bitmap{ nullptr };
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
wxStaticBitmap* m_mirror_warning_bitmap{ nullptr };
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
// Currently focused editor (nullptr if none)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "libslic3r/TriangleMeshSlicer.hpp"
|
||||
|
||||
#include "imgui/imgui_internal.h"
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -913,7 +914,7 @@ void GLGizmoCut3D::on_register_raycasters_for_picking()
|
|||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i + m_connectors_group_id, *(m_shapes[connectors[i].attribs]).mesh_raycaster, Transform3d::Identity()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (!cut_line_processing()) {
|
||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, X, *m_cone.mesh_raycaster, Transform3d::Identity()));
|
||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, X, *m_cone.mesh_raycaster, Transform3d::Identity()));
|
||||
|
||||
|
@ -991,7 +992,7 @@ void GLGizmoCut3D::update_raycasters_for_picking_transform()
|
|||
m_raycasters[i]->set_transform(translation_transform(pos) * m_rotation_m * scale_trafo);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (!cut_line_processing()){
|
||||
const Transform3d trafo = translation_transform(m_plane_center) * m_rotation_m;
|
||||
|
||||
const BoundingBoxf3 box = bounding_box();
|
||||
|
@ -1376,10 +1377,14 @@ void GLGizmoCut3D::init_rendering_items()
|
|||
init_from_angle_arc(m_angle_arc, m_angle, m_grabber_connection_len);
|
||||
|
||||
if (!m_plane.is_initialized() && !m_hide_cut_plane && !m_connectors_editing) {
|
||||
#if 1
|
||||
m_plane.init_from(its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, 0.3, m_cut_plane_as_circle ? 180 : 4));
|
||||
#else
|
||||
if (m_cut_plane_as_circle)
|
||||
m_plane.init_from(its_make_frustum_dowel(2. * m_radius, 0.3, 180));
|
||||
else
|
||||
m_plane.init_from(its_make_square_plane(float(m_radius)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1419,9 +1424,13 @@ void GLGizmoCut3D::on_render()
|
|||
m_selection_rectangle.render(m_parent);
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_debug_input_window()
|
||||
void GLGizmoCut3D::render_debug_input_window(float x)
|
||||
{
|
||||
m_imgui->begin(wxString("DEBUG"));
|
||||
|
||||
ImVec2 pos = ImGui::GetWindowPos();
|
||||
pos.x = x;
|
||||
ImGui::SetWindowPos(pos, ImGuiCond_Always);
|
||||
/*
|
||||
static bool hide_clipped = false;
|
||||
static bool fill_cut = false;
|
||||
|
@ -1434,12 +1443,20 @@ void GLGizmoCut3D::render_debug_input_window()
|
|||
m_imgui->slider_float("contour_width", &contour_width, 0.f, 3.f);
|
||||
if (auto oc = m_c->object_clipper())
|
||||
oc->set_behavior(hide_clipped || m_connectors_editing, fill_cut || m_connectors_editing, double(contour_width));
|
||||
*/
|
||||
ImGui::PushItemWidth(0.5f * m_label_width);
|
||||
if (auto oc = m_c->object_clipper(); oc && m_imgui->slider_float("contour_width", &m_contour_width, 0.f, 3.f))
|
||||
oc->set_behavior(m_connectors_editing, m_connectors_editing, double(m_contour_width));
|
||||
|
||||
ImGui::Separator();
|
||||
*/
|
||||
|
||||
if (m_imgui->checkbox(_L("Render cut plane as circle"), m_cut_plane_as_circle))
|
||||
m_plane.reset();
|
||||
|
||||
ImGui::PushItemWidth(0.5f * m_label_width);
|
||||
if (m_imgui->slider_float("cut_plane_radius_koef", &m_cut_plane_radius_koef, 1.f, 2.f))
|
||||
m_plane.reset();
|
||||
|
||||
m_imgui->end();
|
||||
}
|
||||
|
||||
|
@ -1481,10 +1498,19 @@ void GLGizmoCut3D::render_shortcuts()
|
|||
if (m_imgui->button("? " + (m_show_shortcuts ? wxString(ImGui::CollapseBtn) : wxString(ImGui::ExpandBtn))))
|
||||
m_show_shortcuts = !m_show_shortcuts;
|
||||
|
||||
if (m_shortcut_label_width < 0.f) {
|
||||
for (const auto& shortcut : m_shortcuts) {
|
||||
const float width = m_imgui->calc_text_size(shortcut.first).x;
|
||||
if (m_shortcut_label_width < width)
|
||||
m_shortcut_label_width = width;
|
||||
}
|
||||
m_shortcut_label_width += +m_imgui->scaled(1.f);
|
||||
}
|
||||
|
||||
if (m_show_shortcuts)
|
||||
for (const auto&shortcut : m_shortcuts ){
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, shortcut.first);
|
||||
ImGui::SameLine(m_label_width);
|
||||
ImGui::SameLine(m_shortcut_label_width);
|
||||
m_imgui->text(shortcut.second);
|
||||
}
|
||||
}
|
||||
|
@ -1624,8 +1650,8 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
|||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(wxString(ImGui::InfoMarkerSmall));
|
||||
ImGui::SameLine();
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _L("Hold SHIFT key and connect some two points of an object to cut by line"));
|
||||
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT,
|
||||
get_wraped_wxString(_L("Hold SHIFT key and connect some two points of an object to cut by line"), 40));
|
||||
ImGui::Separator();
|
||||
|
||||
render_build_size();
|
||||
|
@ -1642,13 +1668,6 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
|||
reset_cut_plane();
|
||||
m_imgui->disabled_end();
|
||||
|
||||
ImGui::SameLine(2.25f * m_label_width);
|
||||
ImGui::PushItemWidth(0.75f * m_label_width);
|
||||
m_is_contour_changed = m_imgui->slider_float("contour width", &m_contour_width, 0.f, 3.f);
|
||||
|
||||
if (auto oc = m_c->object_clipper(); oc && m_is_contour_changed)
|
||||
oc->set_behavior(m_connectors_editing, m_connectors_editing, double(m_contour_width));
|
||||
|
||||
if (wxGetApp().plater()->printer_technology() == ptFFF) {
|
||||
m_imgui->disabled_begin(!m_keep_upper || !m_keep_lower);
|
||||
if (m_imgui->button(_L("Add/Edit connectors")))
|
||||
|
@ -1658,18 +1677,25 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
|||
|
||||
ImGui::Separator();
|
||||
|
||||
auto render_part_action_line = [this, connectors](const wxString& label, const wxString& suffix, bool& keep_part, bool& place_on_cut_part, bool& rotate_part) {
|
||||
float label_width = 0;
|
||||
for (const wxString& label : {_L("Upper part"), _L("Lower part")}) {
|
||||
const float width = m_imgui->calc_text_size(label).x + m_imgui->scaled(1.5f);
|
||||
if (label_width < width)
|
||||
label_width = width;
|
||||
}
|
||||
|
||||
auto render_part_action_line = [this, label_width, connectors](const wxString& label, const wxString& suffix, bool& keep_part, bool& place_on_cut_part, bool& rotate_part) {
|
||||
bool keep = true;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(label);
|
||||
|
||||
ImGui::SameLine(m_label_width);
|
||||
ImGui::SameLine(label_width);
|
||||
|
||||
m_imgui->disabled_begin(!connectors.empty());
|
||||
m_imgui->checkbox(_L("Keep") + suffix, connectors.empty() ? keep_part : keep);
|
||||
m_imgui->disabled_end();
|
||||
|
||||
ImGui::SameLine(2 * m_label_width);
|
||||
ImGui::SameLine();
|
||||
|
||||
m_imgui->disabled_begin(!keep_part);
|
||||
if (m_imgui->checkbox(_L("Place on cut") + suffix, place_on_cut_part))
|
||||
|
@ -1813,7 +1839,8 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
|||
|
||||
m_imgui->end();
|
||||
|
||||
render_debug_input_window();
|
||||
if (!m_connectors_editing) // connectors mode
|
||||
render_debug_input_window(x);
|
||||
}
|
||||
|
||||
// get volume transformation regarding to the "border". Border is related from the size of connectors
|
||||
|
|
|
@ -111,7 +111,9 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||
bool force_update_clipper_on_render{false};
|
||||
|
||||
float m_contour_width{ 0.4f };
|
||||
float m_cut_plane_radius_koef{ 1.5f };
|
||||
bool m_is_contour_changed{ false };
|
||||
float m_shortcut_label_width{ -1.f };
|
||||
|
||||
mutable std::vector<bool> m_selected; // which pins are currently selected
|
||||
int m_selected_count{ 0 };
|
||||
|
@ -199,7 +201,7 @@ protected:
|
|||
void on_stop_dragging() override;
|
||||
void on_render() override;
|
||||
|
||||
void render_debug_input_window();
|
||||
void render_debug_input_window(float x);
|
||||
void adjust_window_position(float x, float y, float bottom_limit);
|
||||
void unselect_all_connectors();
|
||||
void select_all_connectors();
|
||||
|
|
|
@ -1359,10 +1359,10 @@ void GLGizmoMeasure::render_dimensioning()
|
|||
action_exit();
|
||||
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->button(_u8L("Scale")))
|
||||
if (m_imgui->button(_CTX(L_CONTEXT("Scale", "Verb"), "Verb")))
|
||||
action_scale(edit_value, curr_value);
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->button(_u8L("Cancel")))
|
||||
if (m_imgui->button(_L("Cancel")))
|
||||
action_exit();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
@ -1991,7 +1991,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
|||
radius = (on_circle - center).norm();
|
||||
if (use_inches)
|
||||
radius = ObjectManipulation::mm_to_in * radius;
|
||||
text += " (" + _u8L("Diameter:") + " " + format_double(2.0 * radius) + units + ")";
|
||||
text += " (" + _u8L("Diameter") + ": " + format_double(2.0 * radius) + units + ")";
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
@ -2004,7 +2004,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
|||
}
|
||||
|
||||
m_imgui->disabled_begin(!m_selected_features.first.feature.has_value());
|
||||
if (m_imgui->button(_u8L("Restart selection"))) {
|
||||
if (m_imgui->button(_L("Restart selection"))) {
|
||||
m_selected_features.reset();
|
||||
m_selected_sphere_raycasters.clear();
|
||||
m_imgui->set_requires_extra_frame();
|
||||
|
|
|
@ -614,7 +614,7 @@ bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event)
|
|||
#if ENABLE_WORLD_COORDINATE
|
||||
TransformationType transformation_type;
|
||||
if (m_parent.get_selection().is_wipe_tower())
|
||||
transformation_type = TransformationType::Instance_Relative_Joint;
|
||||
transformation_type = TransformationType::World_Relative_Joint;
|
||||
else {
|
||||
switch (wxGetApp().obj_manipul()->get_coordinates_type())
|
||||
{
|
||||
|
|
|
@ -119,10 +119,10 @@ Selection::Selection()
|
|||
{
|
||||
this->set_bounding_boxes_dirty();
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
m_axes.set_stem_radius(0.15f);
|
||||
m_axes.set_stem_length(3.0f);
|
||||
m_axes.set_tip_radius(0.45f);
|
||||
m_axes.set_tip_length(1.5f);
|
||||
m_axes.set_stem_radius(0.5f);
|
||||
m_axes.set_stem_length(20.0f);
|
||||
m_axes.set_tip_radius(1.5f);
|
||||
m_axes.set_tip_length(5.0f);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
|
@ -828,18 +828,15 @@ void Selection::translate(const Vec3d& displacement, TransformationType transfor
|
|||
assert(is_from_fully_selected_instance(i));
|
||||
if (transformation_type.world())
|
||||
v.set_instance_transformation(Geometry::translation_transform(displacement) * volume_data.get_instance_full_matrix());
|
||||
else if (transformation_type.local()) {
|
||||
else if (transformation_type.instance()) {
|
||||
const Vec3d world_displacement = volume_data.get_instance_rotation_matrix() * displacement;
|
||||
v.set_instance_transformation(Geometry::translation_transform(world_displacement) * volume_data.get_instance_full_matrix());
|
||||
}
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
else {
|
||||
const Vec3d offset = transformation_type.local() ?
|
||||
(Vec3d)(volume_data.get_volume_transform().get_rotation_matrix() * displacement) : displacement;
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(offset));
|
||||
}
|
||||
else
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
|
||||
}
|
||||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
|
@ -918,7 +915,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
|||
else {
|
||||
if (transformation_type.world())
|
||||
new_rotation_matrix = rotation_matrix * inst_trafo.get_rotation_matrix();
|
||||
else if (transformation_type.local())
|
||||
else if (transformation_type.instance())
|
||||
new_rotation_matrix = inst_trafo.get_rotation_matrix() * rotation_matrix;
|
||||
else
|
||||
assert(false);
|
||||
|
@ -931,13 +928,14 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
|||
inst_trafo.get_scaling_factor_matrix(), inst_trafo.get_mirror_matrix()));
|
||||
}
|
||||
else {
|
||||
if (transformation_type.absolute()) {
|
||||
const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform();
|
||||
v.set_volume_transformation(Geometry::assemble_transform(volume_trafo.get_offset_matrix(), Geometry::rotation_transform(rotation),
|
||||
volume_trafo.get_scaling_factor_matrix(), volume_trafo.get_mirror_matrix()));
|
||||
if (!is_single_volume_or_modifier()) {
|
||||
assert(transformation_type.world());
|
||||
transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
transformation_type.set_independent();
|
||||
transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center);
|
||||
}
|
||||
else
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::rotation_transform(rotation));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -948,7 +946,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
|||
SyncRotationType synch;
|
||||
if (transformation_type.world() && rot_axis_max == 2)
|
||||
synch = SyncRotationType::NONE;
|
||||
else if (transformation_type.local())
|
||||
else if (transformation_type.instance())
|
||||
synch = SyncRotationType::FULL;
|
||||
else
|
||||
synch = SyncRotationType::GENERAL;
|
||||
|
@ -1283,6 +1281,13 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume)
|
|||
}
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void Selection::mirror(Axis axis, TransformationType transformation_type)
|
||||
{
|
||||
const Vec3d mirror((axis == X) ? -1.0 : 1.0, (axis == Y) ? -1.0 : 1.0, (axis == Z) ? -1.0 : 1.0);
|
||||
scale_and_translate(mirror, Vec3d::Zero(), transformation_type);
|
||||
}
|
||||
#else
|
||||
void Selection::mirror(Axis axis)
|
||||
{
|
||||
if (!m_valid)
|
||||
|
@ -1305,6 +1310,7 @@ void Selection::mirror(Axis axis)
|
|||
|
||||
set_bounding_boxes_dirty();
|
||||
}
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation, TransformationType transformation_type)
|
||||
|
@ -1322,24 +1328,32 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
|
|||
if (transformation_type.absolute()) {
|
||||
// convert from absolute scaling to relative scaling
|
||||
BoundingBoxf3 original_box;
|
||||
BoundingBoxf3 reference_box = m_box.get_bounding_box();
|
||||
if (m_mode == Instance) {
|
||||
assert(is_from_fully_selected_instance(i));
|
||||
if (is_single_full_instance()) {
|
||||
if (transformation_type.world())
|
||||
original_box = get_full_unscaled_instance_bounding_box();
|
||||
else
|
||||
original_box = get_full_unscaled_instance_local_bounding_box();
|
||||
}
|
||||
else
|
||||
original_box = get_bounding_box();
|
||||
}
|
||||
else {
|
||||
if (transformation_type.world())
|
||||
original_box = v.transformed_convex_hull_bounding_box((volume_data.get_instance_transform() *
|
||||
volume_data.get_volume_transform()).get_matrix_no_scaling_factor());
|
||||
if (!is_single_volume_or_modifier())
|
||||
original_box = get_bounding_box();
|
||||
else if (transformation_type.world())
|
||||
original_box = get_bounding_box();
|
||||
else if (transformation_type.instance())
|
||||
original_box = v.transformed_convex_hull_bounding_box(volume_data.get_volume_transform().get_matrix_no_scaling_factor());
|
||||
else
|
||||
original_box = v.transformed_convex_hull_bounding_box(volume_data.get_volume_transform().get_matrix());
|
||||
else {
|
||||
original_box = v.bounding_box();
|
||||
reference_box = v.bounding_box().transformed(volume_data.get_volume_transform().get_scaling_factor_matrix());
|
||||
}
|
||||
transformation_type.set_relative();
|
||||
}
|
||||
|
||||
relative_scale = original_box.size().cwiseProduct(scale).cwiseQuotient(m_box.get_bounding_box().size());
|
||||
relative_scale = original_box.size().cwiseProduct(scale).cwiseQuotient(reference_box.size());
|
||||
}
|
||||
|
||||
if (m_mode == Instance) {
|
||||
|
@ -1353,7 +1367,7 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
|
|||
Geometry::translation_transform(translation) * inst_trafo.get_offset_matrix();
|
||||
v.set_instance_transformation(offset_matrix * scale_matrix * inst_trafo.get_matrix_no_offset());
|
||||
}
|
||||
else if (transformation_type.local()) {
|
||||
else if (transformation_type.instance()) {
|
||||
const Transform3d scale_matrix = Geometry::scale_transform(relative_scale);
|
||||
Vec3d offset;
|
||||
if (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) {
|
||||
|
@ -1370,8 +1384,16 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
|
|||
else
|
||||
assert(false);
|
||||
}
|
||||
else
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale));
|
||||
else {
|
||||
if (!is_single_volume_or_modifier()) {
|
||||
assert(transformation_type.world());
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
transformation_type.set_independent();
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
|
@ -1707,8 +1729,8 @@ void Selection::render(float scale_factor)
|
|||
}
|
||||
else if (coordinates_type == ECoordinatesType::Local && is_single_volume_or_modifier()) {
|
||||
const GLVolume& v = *get_first_volume();
|
||||
box = v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_scaling_factor_matrix());
|
||||
trafo = v.get_instance_transformation().get_matrix() * v.get_volume_transformation().get_matrix_no_scaling_factor();
|
||||
box = v.bounding_box();
|
||||
trafo = v.world_matrix();
|
||||
}
|
||||
else {
|
||||
const Selection::IndicesList& ids = get_volume_idxs();
|
||||
|
@ -1716,9 +1738,7 @@ void Selection::render(float scale_factor)
|
|||
const GLVolume& v = *get_volume(id);
|
||||
box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix()));
|
||||
}
|
||||
const Geometry::Transformation inst_trafo = get_first_volume()->get_instance_transformation();
|
||||
box = box.transformed(inst_trafo.get_scaling_factor_matrix());
|
||||
trafo = inst_trafo.get_matrix_no_scaling_factor();
|
||||
trafo = get_first_volume()->get_instance_transformation().get_matrix();
|
||||
}
|
||||
|
||||
render_bounding_box(box, trafo, ColorRGB::WHITE());
|
||||
|
@ -1856,7 +1876,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field)
|
|||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (!boost::starts_with(sidebar_field, "layer")) {
|
||||
if (!wxGetApp().obj_manipul()->is_world_coordinates())
|
||||
if (wxGetApp().obj_manipul()->is_instance_coordinates())
|
||||
m_axes.render(Geometry::translation_transform(axes_center) * orient_matrix, 0.25f);
|
||||
}
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
@ -3021,17 +3041,24 @@ void Selection::paste_objects_from_clipboard()
|
|||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void Selection::transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
|
||||
const Transform3d& transform)
|
||||
const Transform3d& transform, const Vec3d& world_pivot)
|
||||
{
|
||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
||||
assert(transformation_type.relative());
|
||||
|
||||
const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform();
|
||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
||||
|
||||
if (transformation_type.world()) {
|
||||
const Vec3d inst_pivot = transformation_type.independent() ? volume_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
|
||||
const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset();
|
||||
const Transform3d new_volume_matrix = inst_matrix_no_offset.inverse() * transform * inst_matrix_no_offset;
|
||||
volume.set_volume_transformation(volume_trafo.get_offset_matrix() * new_volume_matrix * volume_trafo.get_matrix_no_offset());
|
||||
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * inst_matrix_no_offset.inverse() * transform * inst_matrix_no_offset * Geometry::translation_transform(-inst_pivot);
|
||||
volume.set_volume_transformation(trafo * volume_trafo.get_matrix());
|
||||
}
|
||||
else if (transformation_type.instance()) {
|
||||
const Vec3d inst_pivot = transformation_type.independent() ? volume_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
|
||||
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot);
|
||||
volume.set_volume_transformation(trafo * volume_trafo.get_matrix());
|
||||
}
|
||||
else if (transformation_type.instance())
|
||||
volume.set_volume_transformation(volume_trafo.get_offset_matrix() * transform * volume_trafo.get_matrix_no_offset());
|
||||
else if (transformation_type.local()) {
|
||||
const Geometry::Transformation trafo(transform);
|
||||
volume.set_volume_transformation(trafo.get_offset_matrix() * volume_trafo.get_matrix() * trafo.get_matrix_no_offset());
|
||||
|
|
|
@ -300,7 +300,7 @@ public:
|
|||
void set_deserialized(EMode mode, const std::vector<std::pair<size_t, size_t>> &volumes_and_instances);
|
||||
|
||||
// Update the selection based on the new instance IDs.
|
||||
void instances_changed(const std::vector<size_t> &instance_ids_selected);
|
||||
void instances_changed(const std::vector<size_t> &instance_ids_selected);
|
||||
// Update the selection based on the map from old indices to new indices after m_volumes changed.
|
||||
// If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances.
|
||||
void volumes_changed(const std::vector<size_t> &map_volume_old_to_new);
|
||||
|
@ -402,11 +402,12 @@ public:
|
|||
void flattening_rotate(const Vec3d& normal);
|
||||
void scale(const Vec3d& scale, TransformationType transformation_type);
|
||||
void scale_to_fit_print_volume(const BuildVolume& volume);
|
||||
void mirror(Axis axis);
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void scale_and_translate(const Vec3d& scale, const Vec3d& translation, TransformationType transformation_type);
|
||||
void mirror(Axis axis, TransformationType transformation_type);
|
||||
void reset_skew();
|
||||
#else
|
||||
void mirror(Axis axis);
|
||||
void translate(unsigned int object_idx, const Vec3d& displacement);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
|
||||
|
@ -501,7 +502,7 @@ private:
|
|||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
|
||||
const Transform3d& transform);
|
||||
const Transform3d& transform, const Vec3d& world_pivot);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue